From: ian Date: Tue, 22 Apr 2008 20:15:14 +0000 (+0000) Subject: before much simpler resolve train placement X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=1cd2822299920478bd911667e60c3215dfacb66c;p=trains.git before much simpler resolve train placement --- diff --git a/hostside/resolve.c b/hostside/resolve.c index c462947..c43e269 100644 --- a/hostside/resolve.c +++ b/hostside/resolve.c @@ -357,26 +357,95 @@ int resolve_complete(void) { return 0; } -static int rtf_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, - MovPosComb *mpc_io, Segment *before) { - if (t->seg->owner != before->owner) - return -1; - t->seg->owner->foredetect= t->seg; +typedef struct { + Train *train; + Segment *foredetect; + int minclear, backwards; +} FindEndUserContext; + +static int segdist(Segment *seg) { + assert(seg->movposcomb >= 0); + 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) { + 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); + return 0; +} +static int findend_trackend(TrackLocation *t, struct TrackAdvanceContext *c) { + FindEndUserContext *u= c->u; + return foundend(u, t->seg); } -static void resolve_train_finalise(Train *tra) { +static void resolve_train_finalise(Segment *startpoint) { + Train *tra; TrackLocation t; TrackAdvanceContext tc; + FindEndUserContext u; - t.seg= tra->foredetect; + 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; + t.backwards= t.seg->tr_backwards ^ tra->backwards; + /* we're going to clear tra->backwards */ + tc.distance= INT_MAX; - tc.nextseg= rtf_nextseg; + tc.nextseg= findend_nextseg; + tc.trackend= findend_trackend; tc.getmovpos= 0; - tc.trackend= 0; + tc.u= &u; + + u.minclear= MARGIN_NOSE + tra->head; + u.backwards= 0; + + r= trackloc_advance(&t,&tc); assert(!r); + + tra->foredetect= u->foredetect; + tra->maxinto= segdist(tra->foredetect) - u->minclear; + 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; +} + + + + + + tra->backwards= 0; + + t.seg= tra->foredetect; + t.remain= 0; trackloc_advance(&t,&tc); + } @@ -412,14 +481,15 @@ void resolve_motioncheck(void) { if (seg->moving) return; FOR_SEG - if (seg->res_detect) { - assert(seg->owner); + if (seg->res_detect) + resolve_train_finalise(seg); + + seg->owner->foredetect= seg; /* initial guess */ } FOR_TRA - resolve_train_finalise(tra); FOR_SEG { if (seg->res_detect) { diff --git a/hostside/safety.c b/hostside/safety.c index 1d00aea..5bca8e3 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -177,7 +177,50 @@ Segment *segments; * committed to in an earlier prediction but which we have not yet * reached in this prediction. * - * (These are the values when not in the middle of nose_nextseg.) */ + * (These are the values when not in the middle of nose_nextseg.) + */ +/* + * Simulation: + * + * DETECT + * real stop dist >>>>> + * simul. stop dist >>>>> + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * set_exactinto FNT + * adv. tail back T FN + * adv. nose find T F N + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * adv. fdet 1 seg T N F + * adv. nose T F N + * adv. tail T F N + * adv. fdet stopdist T N F N + * adv. nose T F N + * adv. tail T F N + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * + * At next detection: + * DETECT + * real stop dist >>>>> + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * set_exactinto FNT + * adv. tail back T FN + * adv. nose find T F N + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * adv. fdet 1 seg T N F + * adv. nose T N ProblemPredicted + * + * Oops, so set sigstopping and speed 0: + * DETECT + * real stop dist >>>>> + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * set_exactinto FNT + * adv. tail back T FN + * adv. nose find T F N + * +++++++++++|+++++++++++|++++++++++|XXXXXX + * adv. fdet 1 seg T N F + * adv. nose T N HorizonReached + * + */ /*========== prediction machinery ==========*/ @@ -244,7 +287,7 @@ static int pred_getmovpos(TrackLocation *t, TrackAdvanceContext *c, PredictUserContext *u= c->u; if (t->seg->motion) *use_io= movpos_change_intent(t->seg->motion); if (*use_io<0) safety_panic(u->train, t->seg, - "track route unexpectedly not known"); + "track route unexpectedly not known"); return 0; } @@ -399,16 +442,20 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, u->nosec.distance= advanced; r= trackloc_advance(&u->nose,&u->nosec); - - if (r==EC_SignallingHorizonReached) { - /* stop our prediction now */ - advanced= u->was_distance= t->remain= 0; - r= 0; + if (r == SignallingHorizonReached && + u->was_distance==INT_MAX) { + /* 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); + int adjust= nose_length(u->train); + if (adjust > u->train->maxinto) adjust= u->train->maxinto; + u->train->maxinto -= adjust; + u->train->uncertainto += adjust; } - if (r) return r; - /* Now we have advanced the nose and have recoreded any appropriate + /* Now we have advanced the nose and have recorded any appropriate * motion(s). But we advancing the nose has updated the segment's * notion of the motion but not trackloc_advance's cached version of * the movposcomb in *mpc_io. That doesn't matter because we don't @@ -446,7 +493,7 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, u->know_best_polarity= 1; } } - if (u->know_best_polarity && + if (u->know_best_polarity && !t->seg->i->invertible && u->noninv_tally[ t->backwards ^ u->train_polarity_inverted ]) { /* incompatible, stop now */ @@ -476,6 +523,10 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, /*---------- prediction entrypoint ----------*/ +static int nose_length(Train *tra) { + return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head); +} + ErrorCode predict_confirm(Train *tra, int accelerate, PredictionProblemCallback *ppc, void *ppcu) { PredictUserContext u; @@ -489,7 +540,7 @@ ErrorCode predict_confirm(Train *tra, int accelerate, } foredet= tra->foredetect; - + memset(&u,0,sizeof(u)); u.train= tra; u.accelerating= accelerate; @@ -521,7 +572,7 @@ ErrorCode predict_confirm(Train *tra, int accelerate, /* find the train's nose */ u.nose= u.fdet; - u.nosec.distance= MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head); + u.nosec.distance= nose_length(tra); u.nosec.nextseg= nose_nextseg; u.nosec.getmovpos= pred_getmovpos; u.nosec.trackend= pred_trackend; @@ -542,13 +593,13 @@ ErrorCode predict_confirm(Train *tra, int accelerate, u.tailc.nextseg= tail_nextseg; ec= trackloc_advance(&u.fdet,&u.fdetc); - if (ec) goto xproblem; + if (ec && ec != EC_SignallingHorizonReached) goto xproblem; /*----- commit to the plan -----*/ if (u.need_polarise) actual_inversions_start(); - + FOR_SEG { if (seg->owner == tra) { seg->det_ignore= seg->det_expected= 0; @@ -604,13 +655,13 @@ void safety_notify_detection(Segment *seg) { Train *tra; TrackLoc tloc; ErrorCode ec; - + if (seg->det_ignore) return; if (!seg->det_expected) safety_panic(0,seg, "unexpected detection"); if (seg->movposcomb < 0) safety_panic(tra,seg, "track route not set and train has arrived"); - + tra= seg->owner; tra->foredetect= seg; tra->uncertainty= tra->maxinto= @@ -618,7 +669,7 @@ void safety_notify_detection(Segment *seg) { ec= predict_confirm(tra, 0, detection_report_problem, 0); if (!ec) return; - + assert(ec == EC_SignallingPredictedProblem); tra->sigstopping= 1; diff --git a/hostside/safety.h b/hostside/safety.h index e80a073..2493373 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -269,7 +269,8 @@ typedef struct TrackAdvanceContext { * May modify *use_io if it wishes. It is OK to leave it as * -1 in which case advance will return whatever getmovpos did * (even if 0). When called by interfering_segment, non-0 returns - * will be treated as an indication that the movposcomb is unknown. */ + * will be treated as an indication that the movposcomb is unknown. + * On entry t->remain is invalid; it should not be modified. */ int (*trackend)(TrackLocation *t, struct TrackAdvanceContext *c); /* trackloc_advance stops even if this returns 0. */ void *u; @@ -289,8 +290,13 @@ Segment *segment_interferes(TrackAdvanceContext *c, Segment *base); int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c); /* Advances t by dist until distance becomes 0, some callback - * returns non-0, or sometimes 0 if we cannot continue and - * the relevant callback is missing or returned 0. */ + * returns non-0, or sometimes 0 if we cannot continue and the + * relevant callback is missing or returned 0. If we exhausted + * c->distance or reached the end of the track then *t is accurate; + * otherwise t is the segment which was problematic (passed to + * nextseg and perhaps getmovpos) and t->remain is set to -1. In + * any case c->distance is updated by the distance successfully + * traversed. */ int trackloc_reverse_exact(TrackLocation *t, TrackAdvanceContext *c); /* c is used just as for trackloc_getlink. diff --git a/hostside/speed.c b/hostside/speed.c index fcdaecf..2a4e013 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -17,7 +17,8 @@ static void decel_done(TimeoutEvent *toev) { tra->speed.speed= tra->speedcurve[tra->speed.step]; if (tra->sigstopping) { assert(!tra->speed.step); - resolve_train_ + train_nose_restricttoowner(tra); + tra->sigstopping= 0; } static const SpeedRange *stop_info(Train *tra, double speed) { diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 96c589d..5dfdffa 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -72,9 +72,9 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { next= &segments[nextnum]; leaving= t->seg; - leaving_back= t->backwards; t->seg= next; t->backwards ^= link->next_backwards; + t->remain= -1; mpc_nego= next->movposcomb; if (c->nextseg) { @@ -83,11 +83,7 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { } r= trackloc_getlink(t,c, &pci,&link, mpc_nego); - if (r || !link) { - t->seg=leaving; - t->backwards= leaving_back; - return r; - } + if (r || !link) return r; t->remain= pci->dist; }