}
const CmdInfo toplevel_cmds[]= {
- { "!pic", cmd_pic, CIXF_ANYSTA|CIXF_FORCE },
- { "!nmra", cmd_nmra, },
- { "noop", cmd_noop, CIXF_ANYSTA },
- { "movpos", cmd_movpos },
- { "!movpos", cmd_movpos, CIXF_ANYSTA|CIXF_FORCE },
- { "speed", cmd_speed },
+ { "!pic", cmd_pic, CIXF_ANYSTA|CIXF_FORCE },
+ { "!nmra", cmd_nmra, },
+ { "noop", cmd_noop, CIXF_ANYSTA },
+ { "movpos", cmd_movpos },
+//{ "autopoint", cmd_autopoint },
+ { "!movpos", cmd_movpos, CIXF_ANYSTA|CIXF_FORCE },
+ { "speed", cmd_speed },
{ 0 }
};
count_time:1,
accelerating:1,
usecurrentposn:1, /* for pred_getmovpos */
+ optimistic:1, /* for autopoint */
alwaysusemotions:1, /* for report_train_ownerships only */
walk_compute_polarise:1, /* nose_nextseg still needs to worry */
need_polarise:1, /* when we commit */
TrackLocation nose, fdet, tail;
TrackAdvanceContext nosec, tailc, fdetc;
TimeInterval elapsed; /* from now, minimum */
- Distance was_distance;
- Segment *hindmost;
+ Distance was_distance, autopoint_distance;
+ Segment *hindmost, *furthest;
PredictionProblemCallback *problem_callback;
void *problem_callback_u;
l= vasprintf(&message, fmt, al); if (l <= 0) diem();
- if (!u->problem_callback)
+ if (u->optimistic)
+ oprintf(DUPO("safety") " predict optimistic problem %s\n", message);
+ else if (!u->problem_callback)
safety_panic(u->train, seg, "unexpected problem predicted"
" (context: %s): %s", (char*)u->problem_callback_u, message);
else
u->problem_callback(u->train, seg, u->problem_callback_u, message);
+ free(message);
return EC_SignallingPredictedProblem;
}
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"
+ " %s%s until=%ld dist=%d (was %d) %c%c%c.%c %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,
"-t"[ u->count_time ],
"-a"[ u->accelerating ],
"-c"[ u->usecurrentposn ],
+ "-o"[ u->optimistic ],
"-w"[ u->walk_compute_polarise ],
"-n"[ u->need_polarise ],
} else {
max_ms= u->elapsed;
}
+
+ if (!u->train->autopoint || !t->seg->autopoint)
+ return predict_problem(u,t->seg,"will not automatically set point");
+
ec= movpos_reserve(t->seg, max_ms, &route_reservation, route_plan, *mpc_io);
if (ec) return predict_problem(u, t->seg, "cannot promise to"
" set route: %s", ec2str(ec));
u->walk_compute_polarise= u->need_polarise=
(t->seg->seg_inverted ^ t->seg->tr_backwards ^
u->train_polarity_inverted);
- }
+
+ if (u->train->autopoint) {
+ const SegPosCombInfo *pci;
+ r= trackloc_getlink(t,c,&pci,0,-1); assert(!r);
+ u->autopoint_distance= pci->dist;
+ }
+ }
if (u->walk_compute_polarise) {
if (t->seg->will_polarise)
return 0;
}
+/*---------- backtracking the optimistic nose ----------*/
+
+static int optunwind_nextseg(TrackLocation *t, TrackAdvanceContext *c,
+ MovPosComb *mpc_io, Segment *before) {
+ PredictUserContext *u= c->u;
+
+ if (t->seg == u->furthest ||
+ t->seg->motion)
+ return EC_SignallingHorizonReached;
+
+ t->seg->pred_present= 0;
+ t->seg->until= 0;
+ return 0;
+}
+
/*---------- reporting position and ownership ----------*/
void report_train_position(Train *tra) {
ec= trackloc_advance(&u.fdet,&u.fdetc);
if (ec && ec != EC_SignallingHorizonReached) goto xproblem;
+ /* look ahead for autopoint */
+
+ oprintf(DUPO("safety") " predict optimism %d\n", u.autopoint_distance);
+
+ if (u.autopoint_distance) {
+ u.furthest= u.nose.seg;
+ u.optimistic= 1;
+ 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.nosec.nextseg= optunwind_nextseg;
+ ec= trackloc_advance(&u.nose,&u.nosec);
+ assert(ec == EC_SignallingHorizonReached);
+ }
+
/*----- commit to the plan -----*/
oprintf(DUPO("safety") " predict committing\n");
Distance maxinto, uncertainty;
unsigned
backwards:1, /* train is moving backwards wrt its own front and back */
+ autopoint:1, /* set points automatically if point has autopoint too */
/* Startup resolution (resolve.c): */
resolution:2; /* for use by speedmanager */
unsigned
tr_backwards:1, /* train's motion is (would be) backwards wrt track */
ho_backwards:1, /* home train has its front and rear backwards wrt track */
+ autopoint:1, /* set points automatically if train has autopoint too */
seg_inverted:1, /* polarity is inverted */
det_ignore:1, det_expected:1, /* safety.c */
moving:1, /* feature(s) have been told to change */
const SegPosCombInfo **pci_r /* 0 ok */,
const SegmentLinkInfo **link_r /* 0 ok */,
MovPosComb mpc /* -1: get from segment */);
- /* Of c, only c->getmovpos is used.
+ /* Of c, only c->getmovpos is used. t->remain is not used.
* c may be 0 which works just like c->getmovpos==0. */
Segment *segment_interferes(TrackAdvanceContext *c, Segment *base);