/* We record R in tra->resolution,
* U in segi->mark0 and D in segi->res_detect */
#define iselem_u mark0
+#define resfin_done mark0
void resolve_begin(void) {
SEG_IV;
typedef struct {
Train *train;
- Segment *foredetect;
- int minclear, backwards;
+ int extraspace;
} FindEndUserContext;
static int segdist(Segment *seg) {
return seg->i->poscombs[seg->movposcomb].dist;
}
-static int foundend(FindEndUserContext *u, Segment *seg) {
- u->foredetect= seg;
- return -1;
-}
-static int findend_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
- MovPosComb *mpc_io, Segment *before) {
+static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
+ MovPosComb *mpc_io, Segment *before) {
FindEndUserContext *u= c->u;
- t->seg->tr_backwards= t->backwards ^ u->backwards;
- if (t->seg->owner != train) return foundend(u, before);
- if (!t->seg->res_detect) { u->minclear= 0; return foundend(u, before);
+ if (t->seg->owner != train) return -1;
+ if (!t->seg->res_detect) { u->extraspace= 0; return -1; }
+
+ u->train->foredetect= seg;
+ t->seg->tr_backwards= t->backwards;
+ t->seg->res_detect= 0;
return 0;
}
-static int findend_trackend(TrackLocation *t, struct TrackAdvanceContext *c) {
- FindEndUserContext *u= c->u;
- return foundend(u, t->seg);
+
+static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
+ MovPosComb *mpc_io, Segment *before) {
+ if (t->seg->owner != train) return -1;
+ t->seg->tr_backwards= !t->backwards;
+ t->seg->resfin_done= 1;
}
static void resolve_train_finalise(Segment *startpoint) {
assert(startpoint->owner);
tra= startpoint->owner;
- startpoint->res_detect= 0; /* clear these as we use them up */
-
t.seg= startpoint;
t.remain= 0;
t.backwards= t.seg->tr_backwards ^ tra->backwards;
- /* we're going to clear tra->backwards */
+
+ tra->backwards= 0;
tc.distance= INT_MAX;
- tc.nextseg= findend_nextseg;
- tc.trackend= findend_trackend;
+ tc.nextseg= findhead_nextseg;
+ tc.trackend= 0;
tc.getmovpos= 0;
tc.u= &u;
- u.minclear= MARGIN_NOSE + tra->head;
- u.backwards= 0;
+ u.extraspace= MARGIN_NOSE + tra->head;
- r= trackloc_advance(&t,&tc); assert(!r);
+ r= findhead_nextseg(&t,&c,0,0); assert(!r);
+ trackloc_advance(&t,&tc);
tra->foredetect= u->foredetect;
- tra->maxinto= segdist(tra->foredetect) - u->minclear;
+ tra->maxinto= segdist(tra->foredetect) - u->extraspace;
if (tra->maxinto < 0) tra->maxinto= 0;
tra->uncertainty= tra->maxinto;
- t.seg= tra->foredetect;
- t.remain=
-
- u->maxinto= u->uncertainty= segdist(before);
-
-
- u->detcanoccupy= tra->head;
- return -1;
-
-t->seg->res_detect
- if (
-
-
- if (t->seg->owner != before->owner)
- return -1;
- t->seg->owner->foredetect= t->seg;
-}
-
-
-
-
+ FOR_SEG {
+ if (seg->owner == tra) seg->res_detect= 0;
+ seg->resfin_done= 0;
+ }
- tra->backwards= 0;
-
t.seg= tra->foredetect;
t.remain= 0;
-
- trackloc_advance(&t,&tc);
- }
-
+ t.backwards= !tra->foredetect->tr_backwards;
+ tc.distance= tra->detectable + tra->tail + MARGIN_NOSE;
+ tc.nextseg= walkback_nextseg;
- for (;;) {
-
-
- Segment *notify, *onwards;
- const SegPosCombInfo *pci;
- const SegmentLinkInfo *link;
-
- notify= seg;
- for (;;) {
- seg->res_detect= 0;
- assert(notify->movposcomb >= 0);
-
- pci= ¬ify->i->poscombs[notify->movposcomb];
- link= &pci->link[notify->tr_backwards];
+ r= walkback_nextseg(&t,&tc,0,0); assert(!r);
+ trackloc_advance(&t,&tc);
- if (!SOMEP(link->next)) break;
- onwards= &segments[link->next];
- if (!onwards->res_detect) break;
- if (onwards->owner != seg->owner) break;
+ if (u->distance) {
+ tra->uncertainty -= u->distance;
+ if (tra->uncertainty < 0)
+ safety_panic(tra, t.seg, "resolved train location too small by %d!",
+ -tra->uncertainty);
+ }
- notify= onwards;
- }
+ FOR_SEG {
+ seg->owner= 0;
+ if (seg->resfin_done) {
+ seg->owner= tra;
+ seg->resfin_done= 0;
+ }
+ }
+}
void resolve_motioncheck(void) {
if (seg->res_detect)
resolve_train_finalise(seg);
-
- seg->owner->foredetect= seg; /* initial guess */
- }
-
-
- FOR_TRA
-
- FOR_SEG {
- if (seg->res_detect) {
-
- safety_notify_detection(notify);
- }
- }
-
sta_finalising_done();
}
static void decel_done(TimeoutEvent *toev) {
Train *tra= (void*)((char*)toev - offsetof(Train, speed.decel));
tra->speed.speed= tra->speedcurve[tra->speed.step];
- if (tra->sigstopping) {
- assert(!tra->speed.step);
- train_nose_restricttoowner(tra);
- tra->sigstopping= 0;
}
static const SpeedRange *stop_info(Train *tra, double speed) {
return xs;
}
+int speedmanager_speed_stopping(Train *tra) {
+ return tra->speed.try_speed < 0 && !tra->speed.speed;
+}
+
ErrorCode speedmanager_speedchange_request(Train *tra, int step,
PredictionProblemCallback *ppc, void *ppcu) {
ErrorCode ec, ec2;
tra->speed.decel.duration= stop_info(tra,vnow)->ts;
toev_start(&tra->speed.decel);
tra->speed.speed= vnow;
+ ec= predict_confirm(tra,0, 0,(char*)"deceleration forbidden");
+ assert(!ec);
xmit(tra);
return 0;
}
toev_stop(&tra->speed.decel);
tra->speed.speed= vtarg;
tra->speed.try_speed= -1;
- tra->sigstopping= 0;
xmit(tra);
return 0;
}
void speedmanager_reset_train(Train *tra) {
Nmra n;
- tra->sigstopping= 0;
tra->speed.step= 0;
toev_init(&tra->speed.decel);
tra->speed.decel.callback= decel_done;