/*---------- heads and tails of trains, final placement ----------*/
#define resfin_ours mark1
-#define resfin_done mark2
typedef struct {
+ Distance hardallow, min, max;
+ int hardwhy;
+ Segment *lastdetect, *hardend;
+} FindEndConstraint;
+
+typedef struct {
+ TrackAdvanceContext tc; /* first! */
+ TrackLocation t;
Train *train;
- Segment *furthest;
- int extraspace;
+ Segment *startpoint;
+ Distance atlastdetect;
+ Segment *lastdetect;
+ FindEndConstraint constraints[2];
+ int problems, rear;
} FindEndUserContext;
static int findends_getmovpos(TrackLocation *t, TrackAdvanceContext *c,
const char *pn= t->seg->i->pname;
if (t->seg->motion) *use_io= movpos_change_intent(t->seg->motion);
if (*use_io<0) {
- DPRINTF(resolving,ends, " getmovpos %s fails\n", pn);
- t->seg->resfin_done= 0;
- return -1;
+ DPRINTF(resolving,ends, " getmovpos %s fails\n", pn);
+ return 'm';
}
- DPRINTF(resolving,ends, " getmovpos %s -> %d\n", pn, *use_io);
+ DPRINTF(resolving,ends, " getmovpos %s -> %d\n", pn, *use_io);
return 0;
}
-static int segdist(Segment *seg) {
- TrackLocation t;
+static int constraint_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
+ MovPosComb *mpc, const TrackLocation *before) {
int r;
- MovPosComb mpc;
-
- t.seg= seg;
- mpc= seg->movposcomb;
+ FindEndUserContext *u= (void*)c;
- r= findends_getmovpos(&t,0,&mpc);
- assert(!r); assert(mpc >= 0);
- return seg->i->poscombs[mpc].dist;
-}
-
-static void ends_callback_debug(const char *what, TrackLocation *t,
- struct TrackAdvanceContext *c) {
- DPRINTF(resolving,ends, " %s"
- " %s%s dist=%d det=%d ours=%d done=%d owner=%s home=%s\n",
- what, t->backwards?"-":"", t->seg->i->pname, c->distance,
+ DPRINTF(resolving,ends, " constraint_nextseg %c"
+ " %s%s dist=INF-%d det=%d ours=%d owner=%s home=%s\n",
+ "fr"[u->rear],
+ t->backwards?"-":"", t->seg->i->pname,
+ TL_DIST_INF - c->distance,
t->seg->res_detect,
t->seg->resfin_ours,
- t->seg->resfin_done,
t->seg->owner ? t->seg->owner->pname : "-",
t->seg->home ? t->seg->home->pname : "-");
-}
-static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
- MovPosComb *mpc_io, const TrackLocation *before) {
- FindEndUserContext *u= c->u;
+ if (!t->seg->resfin_ours) return 'o';
+ r= findends_getmovpos(t,0,mpc); if (r) return r;
- ends_callback_debug("findhead_nextseg",t,c);
+ const SegPosCombInfo *pci= &t->seg->i->poscombs[*mpc];
- if (!t->seg->resfin_ours || t->seg->resfin_done) return -1;
- u->furthest= t->seg;
- t->seg->tr_backwards= t->backwards;
- t->seg->resfin_done= 1;
-
- if (!t->seg->res_detect) {
- u->train->plan_lookahead_nsegs= 1;
- u->extraspace= 0;
- return -1;
+ if (before) {
+ if (t->seg == u->startpoint) return 'l';
+ const SegmentLinkInfo *rlink= &pci->link[!t->backwards];
+ if (before->seg != &segments[rlink->next]) return 'm';
+ }
+ if (t->seg->res_detect) {
+ u->atlastdetect= c->distance;
+ u->lastdetect= t->seg;
}
- u->train->foredetect= t->seg;
return 0;
}
-static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
- MovPosComb *mpc_io, const TrackLocation *before) {
- ends_callback_debug("walkback_nextseg",t,c);
+static int constraint_trackend(TrackLocation *t,
+ struct TrackAdvanceContext *c) {
+ return 'e';
+}
- if (!t->seg->resfin_ours) return -1;
- t->seg->tr_backwards= !t->backwards;
- t->seg->resfin_done= 1;
- return 0;
+static void end_startpoint(FindEndUserContext *u) {
+ int r;
+
+ u->tc.distance= TL_DIST_INF;
+ u->tc.nextseg= constraint_nextseg;
+ u->tc.getmovpos= findends_getmovpos;
+ u->tc.trackend= constraint_trackend;
+ u->tc.u= 0;
+
+ r= trackloc_set_exactinto(&u->t, &u->tc,
+ u->startpoint, u->startpoint->tr_backwards,
+ 0);
+ assert(!r);
+}
+
+static void end_constraints(FindEndUserContext *u) {
+ FindEndConstraint lim;
+ Train *tra= u->train;
+ int r;
+
+ end_startpoint(u);
+ u->tc.distance= TL_DIST_INF;
+
+ u->lastdetect= 0;
+ u->atlastdetect= -1;
+
+ if (u->rear) {
+ r= trackloc_reverse_exact(&u->t,&u->tc);
+ assert(!r);
+ }
+
+ FindEndConstraint *cons= &u->constraints[u->rear];
+
+ cons->hardwhy= trackloc_advance(&u->t,&u->tc);
+
+ assert(cons->hardwhy);
+ assert(u->lastdetect);
+ assert(u->atlastdetect >= 0);
+
+ Distance nose= MARGIN_NOSE +
+ ((tra->backwards ^ u->rear) ? tra->head : tra->tail);
+
+ lim.min= TL_DIST_INF - u->atlastdetect;
+ lim.max= (TL_DIST_INF - u->tc.distance) - nose;
+
+ if (!u->rear) {
+ cons->min= lim.min;
+ cons->max= lim.max;
+ } else {
+ cons->max= -lim.min + tra->detectable;
+ cons->min= -lim.max + tra->detectable;
+ }
+ cons->lastdetect= u->lastdetect;
+ cons->hardend= u->t.seg;
+
+ if (cons->min > cons->max) {
+ ouprintf("resolution implausible %s %s overhang %d %d\n",
+ cons->lastdetect->i->pname, tra->pname,
+ cons->min - cons->max, nose);
+ u->problems++;
+ }
+
+ DPRINTF(resolving,ends, " lims %c hardwhy=%c %s,%s lim=%d..%d out=%d..%d\n",
+ "fr"[u->rear], cons->hardwhy,
+ cons->lastdetect->i->pname, u->t.seg->i->pname,
+ lim.min, lim.max, cons->min, cons->max);
}
static int resolve_complete_ends_train(Train *tra) {
SEG_IV;
- TrackLocation t;
- TrackAdvanceContext tc;
FindEndUserContext u;
- Segment *startpoint;
+ const SegPosCombInfo *pci;
+ struct timeval tnow;
+ ErrorCode ec;
+ int r, DP;
switch (tra->resolution) {
case RR_H: break;
default: abort();
}
- DPRINTF(resolving,ends, "%s %c\n",
- tra->pname, RESOLUTION_CHARS[tra->resolution]);
+ DPRINTF1(resolving,ends, "%s %c",
+ tra->pname, RESOLUTION_CHARS[tra->resolution]);
- startpoint= 0;
+ memset(&u,0,sizeof(u));
+ u.startpoint= 0;
FOR_SEGMENT(seg,NOOP,NOOP) {
- seg->resfin_done= 0;
seg->resfin_ours= tra ==
(tra->resolution==RR_H ? seg->home : seg->owner);
- if (seg->resfin_ours && seg->res_detect)
- startpoint= seg;
+ if (!seg->resfin_ours) continue;
+ DPRINTF2(" %s%s", seg->tr_backwards?"-":"", seg->i->pname);
+ if (seg->res_detect) {
+ DPRINTF2("*");
+ u.startpoint= seg;
+ }
}
-
- assert(startpoint);
-
- t.seg= startpoint;
- t.remain= 0;
- t.backwards= t.seg->tr_backwards ^ tra->backwards;
-
- tra->backwards= 0;
- tra->plan_lookahead_nsegs= 0;
-
- tc.distance= TL_DIST_INF;
- tc.nextseg= findhead_nextseg;
- tc.getmovpos= findends_getmovpos;
- tc.trackend= 0;
- tc.u= &u;
+ assert(u.startpoint);
+ DPRINTF2("\n");
+
+ /* There are four pieces of information we have:
+ * The rearmost detection, the rearmost end of ownership
+ * the foremost detection, the foremost end of ownership
+ *
+ * From each we compute a range of locations. These are
+ * in the form of a minimum and maximum distance of the
+ * foredetect ahead of 0 into the startpoint.
+ */
u.train= tra;
- u.extraspace= MARGIN_NOSE + tra->head;
- u.furthest= 0;
-
- DPRINTF(resolving,ends, " start=%s%s es=%d\n",
- t.backwards?"-":"", t.seg->i->pname, u.extraspace);
-
- trackloc_advance(&t,&tc);
+ for (u.rear=0; u.rear<2; u.rear++)
+ end_constraints(&u);
- DPRINTF(resolving,ends, " es=%d furthest=%s fd=%s%s fd.dist=%d\n",
- u.extraspace, u.furthest->i->pname,
- tra->foredetect->tr_backwards?"-":"", tra->foredetect->i->pname,
- segdist(tra->foredetect));
+ Distance wrongness;
- tra->maxinto= segdist(tra->foredetect) - u.extraspace;
- if (tra->maxinto < 0) {
- ouprintf("resolution mispositioned head %s %s %d\n",
- tra->pname, tra->foredetect->i->pname, -tra->maxinto);
- return 1;
+ if ((wrongness= u.constraints[0].min - u.constraints[1].max) > 0) {
+ for (u.rear=1; u.rear>0; u.rear--)
+ ouprintf("resolution implausible %s %s over-detect %d\n",
+ u.constraints[u.rear].lastdetect->i->pname,
+ tra->pname, wrongness);
+ u.problems++;
}
- tra->uncertainty= tra->maxinto;
+ if ((wrongness= u.constraints[1].min - u.constraints[0].max) > 0) {
+ for (u.rear=1; u.rear>0; u.rear--)
+ ouprintf("resolution implausible %s %s cramped %d\n",
+ u.constraints[u.rear].hardend->i->pname,
+ tra->pname, wrongness);
+ u.problems++;
+ }
+
+ int min= MIN(u.constraints[0].min, u.constraints[1].min);
+ int max= MIN(u.constraints[0].max, u.constraints[1].max);
+ DPRINTF(resolving,ends, " lims a %d..%d problems=%d\n",
+ min, max, u.problems);
- t.seg= tra->foredetect;
- t.remain= 0;
- t.backwards= !tra->foredetect->tr_backwards;
+ if (u.problems)
+ return u.problems;
- tc.distance= tra->detectable + tra->tail + MARGIN_NOSE;
- tc.nextseg= walkback_nextseg;
+ assert(min <= max);
+ assert(max > 0); /* startpoint is detected so foredet is there or later */
- trackloc_advance(&t,&tc);
+ /* Now we just need to turn this into the canonical format. */
- DPRINTF(resolving,ends, " maxi=%d unc=%d;"
- " remaining distance=%d\n",
- tra->maxinto, tra->uncertainty, tc.distance);
+ end_startpoint(&u);
- if (tc.distance) {
- tra->uncertainty -= tc.distance;
- if (tra->uncertainty < 0) {
- ouprintf("resolution mispositioned tail %s %s %d\n",
- tra->pname, t.seg->i->pname, -tra->uncertainty);
- return 1;
- }
- }
+ u.tc.distance= max;
+ r= trackloc_advance(&u.t, &u.tc); assert(!r);
- FOR_SEG {
- if (seg->owner == tra)
- seg->owner= 0;
+ tra->foredetect= u.t.seg;
+ tra->foredetect->tr_backwards= u.t.backwards;
- if (seg->resfin_done) {
- seg->owner= tra;
- seg->resfin_done= 0;
- seg->det_ignore= 1;
- }
- }
+ r= trackloc_getlink(&u.t, &u.tc, &pci,0,0); assert(!r);
+ tra->maxinto= pci->dist - u.t.remain;
+ tra->uncertainty= max - min;
report_train_position(tra);
- report_train_ownerships(tra, t.seg, 1);
+
+ mgettimeofday(&tnow);
+ tra->plan_lookahead_nsegs= INT_MAX;
+ ec= predict(tra,tnow, PREDF_OLDPLAN, 0,0, 0,
+ 0,(char*)"resolution confirmation");
+ assert(!ec);
return 0;
}