TrackAdvanceContext nosec, tailc, fdetc;
TimeInterval elapsed; /* from now, minimum */
Distance was_distance, autopoint_distance;
+ double maxspeed;
Segment *hindmost, *furthest;
PredictionProblemCallback *problem_callback;
static int nose_length(Train *tra) {
return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head);
}
+static void advance_elapsed(PredictUserContext *u, int advance_distance) {
+ u->elapsed += advance_distance / u->maxspeed;
+}
+static int calc_advanced(TrackAdvanceContext *c) {
+ PredictUserContext *u= c->u;
+ return u->was_distance - c->distance;
+}
/*---------- prediction problem reporting ----------*/
}
static void pred_callback_debug(const char *what, TrackLocation *t,
- struct TrackAdvanceContext *c) {
+ struct TrackAdvanceContext *c,
+ const TrackLocation *before) {
PredictUserContext *u= c->u;
oprintf(DUPO("safety") " predict %s"
- " %s%s until=%ld dist=%d (was %d) %c%c%c.%c %c%c%c%c.%c%c%c%c"
+ " %s%s dist=%-4d until=%-4ld %c%c%c.%c (was %s%s dist=%-4d)"
+ " %c%c%c%c.%c%c%c%c"
" elapsed=%ld nit=%d,%d\n",
what,
- t->backwards?"-":"", t->seg->i->pname, (long)t->seg->until,
- c->distance, u->was_distance,
-
+
+ t->backwards?"-":"",
+ t->seg->i->pname,
+ c->distance,
+ (long)t->seg->until,
+
"-N"[ t->seg->now_present ],
"-P"[ t->seg->pred_present ],
"-V"[ t->seg->pred_vacated ],
- "-#"[ t->seg->will_polarise ],
+ "-p"[ t->seg->will_polarise ],
+
+ before && before->backwards?"-":"",
+ before ? before->seg->i->pname : "-",
+ u->was_distance,
"-t"[ u->count_time ],
"-a"[ u->accelerating ],
}
static int initpresent_nextseg(TrackLocation *t, TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *before) {
+ MovPosComb *mpc_io,
+ const TrackLocation *before) {
PredictUserContext *u= c->u;
t->seg->now_present= t->seg->pred_present= t->seg->will_polarise= 1;
t->seg->until= 0;
/*---------- prediction nose advancement ----------*/
static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *before) {
+ MovPosComb *mpc_io, const TrackLocation *before) {
PredictUserContext *u= c->u;
Segment *interferer;
MovPosComb route_plan;
TimeInterval max_ms;
ErrorCode ec;
- pred_callback_debug(" nose_nextseg",t,c);
+ if (!before) return 0;
+ pred_callback_debug(" nose_nextseg",t,c,before);
+
+ if (u->optimistic)
+ advance_elapsed(u,calc_advanced(c));
/* Is it empty ? */
if (t->seg->pred_present)
return predict_problem(u, t->seg, "will collide with itself!");
- interferer= segment_interferes(c,t->seg);
- if (interferer) {
- if (interferer->owner && interferer->owner != u->train)
- return predict_problem(u, t->seg, "impeded by %s at %s",
- interferer->owner->pname, interferer->i->pname);
- if (interferer->pred_present)
- return predict_problem(u, t->seg, "will collide with itself at %s!",
- interferer->i->pname);
+ if (!u->optimistic) {
+ interferer= segment_interferes(c,t->seg);
+ if (interferer) {
+ if (interferer->owner && interferer->owner != u->train)
+ return predict_problem(u, t->seg, "impeded by %s at %s",
+ interferer->owner->pname, interferer->i->pname);
+ if (interferer->pred_present)
+ return predict_problem(u, t->seg, "will collide with itself at %s!",
+ interferer->i->pname);
+ }
}
/* What about the route ? */
}
} else {
/* Extend the plan. */
- ec= movpos_findcomb_bysegs(before,t->seg,0,*mpc_io, &route_plan);
+ ec= movpos_findcomb_bysegs(before->seg,t->seg,0,*mpc_io, &route_plan);
assert(!ec); /* there must be _some_ route since
we're moving into t->seg */
}
}
if (!u->train->autopoint || !t->seg->autopoint)
- return predict_problem(u,t->seg,"will not automatically set point");
+ return predict_problem(u,t->seg,"will not automatically set route");
ec= movpos_reserve(t->seg, max_ms, &route_reservation, route_plan, *mpc_io);
if (ec) return predict_problem(u, t->seg, "cannot promise to"
/*---------- prediction tail advancement ----------*/
static int tail_nextseg(TrackLocation *t, TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *leaving) {
+ MovPosComb *mpc_io, const TrackLocation *before) {
PredictUserContext *u= c->u;
- pred_callback_debug(" tail_nextseg",t,c);
+ if (!before) return 0;
+ pred_callback_debug(" tail_nextseg",t,c,before);
if (!t->seg->i->invertible)
- u->noninv_tally[leaving->tr_backwards]--;
+ u->noninv_tally[before->seg->tr_backwards]--;
- if (leaving->pred_vacated) return 0; /* only vacate once */
- leaving->pred_present= 0;
- leaving->pred_vacated= 1;
- leaving->until= u->elapsed;
+ if (before->seg->pred_vacated) return 0; /* only vacate once */
+ before->seg->pred_present= 0;
+ before->seg->pred_vacated= 1;
+ before->seg->until= u->elapsed;
return 0;
}
/*---------- prediction foredetect advancement ----------*/
static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *before) {
+ MovPosComb *mpc_io, const TrackLocation *before) {
PredictUserContext *u= c->u;
int advanced, r;
* the previous segment.
*/
- pred_callback_debug("fdet_nextseg",t,c);
+ if (!before) return 0;
+ pred_callback_debug("fdet_nextseg",t,c,before);
- advanced= u->was_distance - c->distance;
+ advanced= calc_advanced(c);
- if (u->count_time) {
- u->elapsed += advanced / speedmanager_speed_maxestimate(u->train);
- }
+ if (u->count_time)
+ advance_elapsed(u,advanced);
u->nosec.distance= advanced;
r= trackloc_advance(&u->nose,&u->nosec);
/* Our very first `next segment' lookahead found the end. So we
* know that our nose hasn't left this segment because that's what
* the stopping distance is supposed to prove. */
- assert(before == u->train->foredetect);
+ assert(before->seg == u->train->foredetect);
int adjust= nose_length(u->train);
if (adjust > u->train->maxinto) adjust= u->train->maxinto;
u->train->maxinto -= adjust;
/*---------- backtracking the optimistic nose ----------*/
static int optunwind_nextseg(TrackLocation *t, TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *before) {
+ MovPosComb *mpc_io, const TrackLocation *before) {
PredictUserContext *u= c->u;
+ pred_callback_debug("optunwind_nextseg",t,c,before);
+
if (t->seg == u->furthest ||
t->seg->motion)
return EC_SignallingHorizonReached;
return 0;
}
-/*---------- reporting position and ownership ----------*/
-
-void report_train_position(Train *tra) {
- oprintf(UPO, "train %s %s at %s%s:%d+-%d\n",
- tra->pname, tra->backwards ? "backwards" : "forwards",
- tra->foredetect->tr_backwards?"-":"",
- tra->foredetect->i->pname, tra->maxinto, tra->uncertainty);
-}
-
-static int report_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
- MovPosComb *mpc, Segment *before) {
- PredictUserContext *u= c->u;
- char flags[6];
- int r;
-
- if (t->seg->owner != u->train) return -1;
- if (t->seg == u->hindmost && t->seg->tr_backwards == t->backwards) {
- /* We've looped the loop. */
- oprintf(UPO, " ...");
- return -1;
- }
-
- flags[0]= 0;
-
- if (t->seg->det_expected)
- strcat(flags,"*");
- if (t->seg->det_ignore)
- strcat(flags,".");
- if (t->seg == u->train->foredetect) {
- strcat(flags,"!");
- u->usecurrentposn= 0;
- }
-
- oprintf(UPO," %s%s", t->backwards?"-":"", t->seg->i->pname);
-
- if (t->seg->i->n_poscombs > 1) {
- r= pred_getmovpos(t,c,mpc); assert(!r); assert(*mpc>=0);
- oprintf(UPO,"/%s", t->seg->i->poscombs[*mpc].pname);
- }
- oprintf(UPO,"%s",flags);
-
- return 0;
-}
-
-void report_train_ownerships(Train *tra, Segment *hindmost,
- int always_use_motions) {
- PredictUserContext u;
- MovPosComb mpc;
- int r;
-
- memset(&u,0,sizeof(u));
- u.train= tra;
- u.hindmost= 0;
- u.alwaysusemotions= always_use_motions;
- u.usecurrentposn= !always_use_motions;
-
- /* Walk along the train printing its segments: */
- oprintf(UPO, "train %s has", tra->pname);
-
- u.nose.seg= hindmost;
- u.nose.remain= 0;
- u.nose.backwards= hindmost->tr_backwards;
-
- u.nosec.distance= TL_DIST_INF;;
- u.nosec.nextseg= report_nextseg;
- u.nosec.getmovpos= pred_getmovpos;
- u.nosec.u= &u;
-
- mpc= u.nose.seg->movposcomb;
- r= report_nextseg(&u.nose,&u.nosec,&mpc,0); assert(!r);
-
- u.hindmost= hindmost;
- trackloc_advance(&u.nose,&u.nosec);
-
- oprintf(UPO, "\n");
-}
-
-
-/*---------- prediction entrypoint ----------*/
+/*========== prediction entrypoint ==========*/
ErrorCode predict(Train *tra, int accelerate,
PredictionProblemCallback *ppc, void *ppcu) {
u.train= tra;
u.problem_callback= ppc;
u.problem_callback_u= ppcu;
+ u.maxspeed= speedmanager_speed_maxestimate(u.train);
- oprintf(DUPO("safety") " predict starting %s%s speed=%f (try %f, step %d%s)"
- " accel=%d\n",
+ oprintf(DUPO("safety") " predict starting %s%s maxspeed=%f"
+ " (speed %f try %f, step %d%s) accel=%d\n",
tra->backwards?"-":"",tra->pname,
- tra->speed.speed, tra->speed.try_speed, tra->speed.step,
+ u.maxspeed, tra->speed.speed, tra->speed.try_speed, tra->speed.step,
tra->speed.decel.running ? " decel" : "",
accelerate);
u.tailc.nextseg= initpresent_nextseg;
u.tailc.trackend= pred_trackend_panic;
- ec= initpresent_nextseg(&u.tail,&u.tailc,0,0); assert(!ec);
ec= trackloc_advance(&u.tail,&u.tailc); assert(!ec);
trackloc_reverse_exact(&u.tail,0);
/* look ahead for autopoint */
- oprintf(DUPO("safety") " predict optimism %d\n", u.autopoint_distance);
+ oprintf(DUPO("safety") " predict optimism %d nose %s\n",
+ u.autopoint_distance, u.nose.seg->i->pname);
if (u.autopoint_distance) {
u.furthest= u.nose.seg;
u.optimistic= 1;
- u.nosec.distance= u.autopoint_distance;
+ u.was_distance= u.nosec.distance= u.autopoint_distance;
trackloc_advance(&u.nose,&u.nosec);
/* But actually we don't want to end up owning
* segments unless we have to for motions. */
u.nose.backwards ^= 1;
+ u.nose.remain= 0;
u.nosec.nextseg= optunwind_nextseg;
+ u.nosec.distance= TL_DIST_INF;
+
ec= trackloc_advance(&u.nose,&u.nosec);
assert(ec == EC_SignallingHorizonReached);
}
oprintf(UPO,
" %s%s%s%c%c%c%c",
seg->tr_backwards?"-":"", seg->i->pname,
- seg->owner == tra ? "#" : "=",
+ seg->owner == tra ? "=" :
+ seg->owner ? "#" : "-" ,
"-N"[ seg->now_present ],
"-P"[ seg->pred_present ],
"-V"[ seg->pred_vacated ],
- "-#"[ seg->will_polarise ]);
+ "-p"[ seg->will_polarise ]);
- if (seg->owner == tra) {
- seg->det_ignore= 0;
- seg->owner= 0;
- }
if (seg->pred_present || seg->pred_vacated) {
seg->owner= tra;
seg->det_ignore= seg->now_present;
+ } else if (seg->owner == tra) {
+ seg->det_ignore= 0;
+ seg->owner= 0;
}
if (seg->motion && !seg->moving && !seg->now_present) {
MovPosChange *reservation= seg->motion;
return ec;
}
+/*========== reporting position and ownership ==========*/
+
+void report_train_position(Train *tra) {
+ oprintf(UPO, "train %s %s at %s%s:%d+-%d\n",
+ tra->pname, tra->backwards ? "backwards" : "forwards",
+ tra->foredetect->tr_backwards?"-":"",
+ tra->foredetect->i->pname, tra->maxinto, tra->uncertainty);
+}
+
+static int report_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
+ MovPosComb *mpc, const TrackLocation *before) {
+ PredictUserContext *u= c->u;
+ char flags[6];
+ int r;
+
+ if (t->seg->owner != u->train) return -1;
+ if (before &&
+ t->seg == u->hindmost &&
+ t->seg->tr_backwards == t->backwards) {
+ /* We've looped the loop. */
+ oprintf(UPO, " ...");
+ return -1;
+ }
+
+ flags[0]= 0;
+
+ if (t->seg->det_expected)
+ strcat(flags,"*");
+ if (t->seg->det_ignore)
+ strcat(flags,".");
+ if (t->seg == u->train->foredetect) {
+ strcat(flags,"!");
+ u->usecurrentposn= 0;
+ }
+
+ oprintf(UPO," %s%s", t->backwards?"-":"", t->seg->i->pname);
+
+ if (t->seg->i->n_poscombs > 1) {
+ r= pred_getmovpos(t,c,mpc); assert(!r); assert(*mpc>=0);
+ oprintf(UPO,"/%s", t->seg->i->poscombs[*mpc].pname);
+ }
+ oprintf(UPO,"%s",flags);
+
+ return 0;
+}
+
+void report_train_ownerships(Train *tra, Segment *hindmost,
+ int always_use_motions) {
+ PredictUserContext u;
+
+ memset(&u,0,sizeof(u));
+ u.train= tra;
+ u.hindmost= 0;
+ u.alwaysusemotions= always_use_motions;
+ u.usecurrentposn= !always_use_motions;
+
+ /* Walk along the train printing its segments: */
+ oprintf(UPO, "train %s has", tra->pname);
+
+ u.nose.seg= hindmost;
+ u.nose.remain= 0;
+ u.nose.backwards= hindmost->tr_backwards;
+
+ u.nosec.distance= TL_DIST_INF;;
+ u.nosec.nextseg= report_nextseg;
+ u.nosec.getmovpos= pred_getmovpos;
+ u.nosec.u= &u;
+ u.hindmost= hindmost;
+
+ trackloc_advance(&u.nose,&u.nosec);
+
+ oprintf(UPO, "\n");
+}
+
+
/*========== entrypoints from rest of the program ==========*/
static void detection_report_problem(Train *tra, Segment *seg,