From: ian Date: Wed, 16 Jul 2008 20:37:14 +0000 (+0000) Subject: safety_setdirection compiles but untested X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=7ec73b1f76976b66376bd50a25f5793bf83a1401;p=trains.git safety_setdirection compiles but untested --- diff --git a/hostside/safety.c b/hostside/safety.c index 0b2a8d4..9c3a10f 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -305,6 +305,13 @@ static int calc_advanced(TrackAdvanceContext *c) { return u->was_distance - c->distance; } +#define SKELETON_PREDICT_USER_CONTEXT(u,tra) \ + (memset(&(u),0,sizeof((u))), \ + (u).problem_callback= ppc, \ + (u).problem_callback_u= ppcu, \ + (u).train= tra) + /* for callers of predict_problem rather than predict */ + /*---------- prediction problem reporting ----------*/ static ErrorCode predict_vproblem(PredictUserContext *u, Segment *seg, @@ -737,7 +744,7 @@ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, /* * If tra->uncertainty > tra->maxinto then in theory the foredetect * might be in the previous segment. We don't take that into account, - * which extends the effective length of the train. + * so we must instead extend our idea of the length of the train. */ int effective_length= MARGIN_TAIL + tail_length(tra) + tra->detectable; @@ -1048,7 +1055,88 @@ void report_train_ownerships(Train *tra, Segment *hindmost, ouprintf("\n"); } + +/*========== reversing a train ==========*/ + +static int reverse_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, + MovPosComb *mpc_io, const TrackLocation *before) { + PredictUserContext *u= c->u; + if (*mpc_io==-1 || t->seg->motion) + return predict_problem(u,t->seg, "segment under train is not stable"); + return 0; +} + +static int reverse_trackend(TrackLocation *t, struct TrackAdvanceContext *c) { + abort(); +} + +ErrorCode safety_setdirection(Train *tra, int backwards, + PredictionProblemCallback *ppc, void *ppcu) { + /* We adjust: + * tra->foredetect, maxinto, uncertainty + * tra->backwards + * tra->plan_lookahead_nsegs + * seg->tr_backwards + * The following remain unchanged as all their users have + * regard to the train's direction: + * tra->head, tail + */ + TrackLocation newfdet; + TrackAdvanceContext c; + PredictUserContext u; + const SegPosCombInfo *pci; + Segment *oldfdet; + int oldmaxinto; + ErrorCode ec, ec2; + int r; + struct timeval tnow; + + SKELETON_PREDICT_USER_CONTEXT(u,tra); + + MUSTECR( safety_checktrain(tra,ppc,ppcu) ); + + if (tra->backwards == backwards) + return 0; + + if (!speedmanager_stopped(tra)) + return predict_problem(&u,0, "train is not stopped"); + newfdet.seg= tra->foredetect; + newfdet.remain= tra->maxinto; + newfdet.backwards= !tra->backwards; + + c.distance= tra->detectable + tra->uncertainty; + c.nextseg= reverse_nextseg; + c.getmovpos= 0; + c.trackend= reverse_trackend; + c.u= &u; + + MUSTECR( trackloc_advance(&newfdet,&c) ); + + mgettimeofday(&tnow); + + /* right, now let's start fiddling */ + oldfdet= tra->foredetect; + oldmaxinto= tra->maxinto; + + r= trackloc_getlink(&newfdet,&c,&pci,0,-1); assert(!r); + tra->foredetect= newfdet.seg; + tra->maxinto= pci->dist - newfdet.remain; + + ec= predict(tra,tnow, PREDF_NEWPLAN,0,0, ppc,ppcu); + if (!ec) return 0; /* yay! */ + + /* It can happen eg that the uncertainty is more troublesome when + * considered one way than the other. In which case just put it back now. */ + assert(ec == EC_SignallingPredictedProblem); + + tra->foredetect= oldfdet; + tra->maxinto= oldmaxinto; + ec2= predict(tra,tnow, 0,0,0, 0,(char*)"abandon reverse"); + assert(!ec2); + + return ec; +} /*========== entrypoints from rest of the program ==========*/ @@ -1108,8 +1196,6 @@ void safety_notify_detection(Segment *seg) { speedmanager_safety_stop(tra,tnow); ec= predict(tra,tnow, PREDF_JUSTDET,0,0, 0,(char*)"safety commanding stop"); assert(!ec); - - assert(!ec); } ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, @@ -1118,22 +1204,19 @@ ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, struct timeval tnow; ErrorCode ec, ec2; - memset(&u,0,sizeof(u)); - u.problem_callback= ppc; - u.problem_callback_u= ppcu; - u.train= seg->owner; + SKELETON_PREDICT_USER_CONTEXT(u,seg->owner); if (!seg->owner) return movpos_change(seg,comb,-1,0); if (allow_queueing<2) { if (seg->det_ignore) - return predict_problem(&u,seg, " route set for train"); + return predict_problem(&u,seg, "route set for train"); if (seg->det_expected) - return predict_problem(&u,seg, " route set for immiment train"); + return predict_problem(&u,seg, "route set for immiment train"); } if (allow_queueing<1) - return predict_problem(&u,seg, " route set for approaching train"); + return predict_problem(&u,seg, "route set for approaching train"); mgettimeofday(&tnow); ec= predict(seg->owner,tnow, PREDF_NEWPLAN,seg,comb, ppc,ppcu); @@ -1145,6 +1228,15 @@ ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, return ec; } +ErrorCode safety_checktrain(Train *tra, + PredictionProblemCallback *ppc, void *ppcu) { + if (!tra->foredetect) { + ppc(tra,0,ppcu,"train is not on layout"); + return EC_SignallingPredictedProblem; + } + return 0; +} + void safety_abandon_run(void) { SEG_IV; diff --git a/hostside/safety.h b/hostside/safety.h index 1f1fdaf..1a74fe0 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -106,8 +106,8 @@ void safety_panic(Train *tra, Segment *seg, const char *fmt,...) typedef void PredictionProblemCallback(Train *tra, Segment *seg /* may be 0 */, void *pu, const char *message); -void safety_setdirection(Train* tra, int backwards); - /* NYI */ +ErrorCode safety_checktrain(Train *tra, + PredictionProblemCallback *ppc, void *ppcu); void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ @@ -120,6 +120,9 @@ ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, * ==2 allows queueing a change for when the train has left */ +ErrorCode safety_setdirection(Train *tra, int backwards, + PredictionProblemCallback *ppc, void *ppcu); + #define PREDF_JUSTDET 001u /* we have just detected the train entering its foredetect so we * can subtract the uncertainty from the stopping distance */ @@ -241,6 +244,7 @@ void speedmanager_reset_train(Train *tra); double speedmanager_speed_maxestimate(Train *tra, struct timeval tnow); double speedmanager_stoppingdistance(Train *tra, struct timeval tnow); int speedmanager_stopping(Train *tra); +int speedmanager_stopped(Train *tra); void actual_speed(Train *tra, int step); diff --git a/hostside/speed.c b/hostside/speed.c index 305b2d0..a405b29 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -99,6 +99,10 @@ int speedmanager_stopping(Train *tra) { return r; } +int speedmanager_stopped(Train *tra) { + return tra->speed.speed == 0; +} + static ErrorCode request_core(Train *tra, int step, struct timeval tnow, PredictionProblemCallback *ppc, void *ppcu) { ErrorCode ec, ec2; @@ -153,10 +157,7 @@ ErrorCode speedmanager_speedchange_request(Train *tra, int step, struct timeval tnow; assert(ppc || ppcu); - if (!tra->foredetect) { - ppc(tra,0,ppcu,"train is not on layout"); - return EC_SignallingPredictedProblem; - } + MUSTECR( safety_checktrain(tra,ppc,ppcu) ); mgettimeofday(&tnow); return request_core(tra,step,tnow,ppc,ppcu); }