From: ian Date: Sun, 18 May 2008 01:08:52 +0000 (+0000) Subject: allegedly, point setting in train's route X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=7d9952ecd6250b4d0f716c07bd4ba5a569b4201e;p=trains.git allegedly, point setting in train's route --- diff --git a/hostside/commands.c b/hostside/commands.c index 244cc87..9b1205c 100644 --- a/hostside/commands.c +++ b/hostside/commands.c @@ -259,10 +259,11 @@ static int cmd_movpos(ParseState *ps, const CmdInfo *ci) { MUSTECR( ps_neednoargs(ps) ); - if (!(ci->xarg & CIXF_FORCE)) - MUSTECRPREDICT( safety_check_movposchange(move,CMDPPC) ); - - MUSTECR( movpos_change(move,poscomb,ms,0) ); + if (ci->xarg & CIXF_FORCE) + MUSTECR( movpos_change(move,poscomb,ms,0) ); + else + MUSTECRPREDICT( safety_movposchange(move, poscomb, ci->xarg & CIXF_U, + CMDPPC) ); return 0; } @@ -300,6 +301,8 @@ const CmdInfo toplevel_cmds[]= { { "!nmra", cmd_nmra, CIXF_ANYSTA }, { "noop", cmd_noop, CIXF_ANYSTA }, { "movpos", cmd_movpos }, + { "route", cmd_movpos, 1 }, + { "reroute", cmd_movpos, 2 }, //{ "autopoint", cmd_autopoint }, { "!movpos", cmd_movpos, CIXF_ANYSTA|CIXF_FORCE }, { "!invert", cmd_invert, CIXF_ANYSTA|CIXF_FORCE }, diff --git a/hostside/realtime.h b/hostside/realtime.h index d405a75..f1aa19c 100644 --- a/hostside/realtime.h +++ b/hostside/realtime.h @@ -113,8 +113,9 @@ extern int picio_send_noise; #define UPO (&(cmdi.out)) -#define CIXF_ANYSTA 1u -#define CIXF_FORCE 2u +#define CIXF_U 0x00ffffu +#define CIXF_ANYSTA 0x010000u +#define CIXF_FORCE 0x020000u /*---------- from/for startup.c ----------*/ diff --git a/hostside/safety.c b/hostside/safety.c index 0a79b9c..8c0d1b9 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -93,13 +93,13 @@ Segment *segments; * until, and remove the departing segments from tallies. * * If all of this works then pred_present and pred_vacated constitute - * the new ownership and motion constitutes the new plan. We commit - * to it by rewriting owner and det_* and actually requesting any - * movfeat changes. + * the new ownership and motion_newplan constitutes the new plan. We + * commit to it by rewriting owner and det_* and actually requesting + * any movfeat changes which we can do now, and replacing motion with + * motion_newplan. * * If not then we issue an signal stop command (we'd better not be - * doing that already!) or countermand the speed increase or whatever. - */ + * doing that already!) or countermand the speed increase or whatever. */ /* * Here is how we use the stuff in the Segment: * @@ -119,7 +119,13 @@ Segment *segments; * the tail leaving it and the head arriving * in each case movpos_change_intent tells us the plan * - * during prediction, motion can be non-0 for + * motion_newplan while we are making a plan this is the new value + * for motion. If identical to motion it + * means we should keep it; if 0 we cancel + * or unreserve; if a different value we + * commit to the new plan instead + * + * during prediction, motion_newplan can be non-0 for * unowned segments as we make our plan. * If we succeed we will end up * owning the segment, and if we fail @@ -253,7 +259,8 @@ typedef struct { TimeInterval elapsed; /* from now, minimum */ Distance was_distance, autopoint_distance, stopping_distance; double maxspeed; - Segment *hindmost, *furthest; + Segment *hindmost, *furthest, *desire_move; + int desire_movposcomb; PredictionProblemCallback *problem_callback; void *problem_callback_u; @@ -393,7 +400,6 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, PredictUserContext *u= c->u; Segment *interferer; MovPosComb route_plan; - MovPosChange *route_reservation; TimeInterval max_ms; ErrorCode ec; @@ -438,15 +444,28 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, if (!t->seg->owner) return predict_problem(u, t->seg, "route not yet set"); if (!u->neednewplan) { + t->seg->motion_newplan= t->seg->motion; *mpc_io= movpos_change_intent(t->seg->motion); goto movement_ok; } } - if (t->seg->motion) { + if (t->seg->motion_newplan) { + route_plan= movpos_change_intent(t->seg->motion); + *mpc_io= route_plan; + goto movement_ok; + } else if (t->seg == u->desire_move && !t->seg->now_present) { + ec= movpos_findcomb_bysegs(before->seg,t->seg,0, + u->desire_movposcomb, &route_plan); + assert(!ec); + if (route_plan != u->desire_movposcomb) + return predict_problem(u, t->seg, " proposed route would be against" + " approaching train"); + } else if (t->seg->motion) { /* We already have a plan. */ route_plan= movpos_change_intent(t->seg->motion); if (!u->neednewplan) { + t->seg->motion_newplan= t->seg->motion; *mpc_io= route_plan; goto movement_ok; } @@ -458,13 +477,11 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, } if (route_plan == *mpc_io && !t->seg->moving) { /* Well, that's all fine then. */ - movpos_unreserve(t->seg->motion); /* we don't need this whatever it is */ - t->seg->motion= 0; goto movement_ok; } - /* We have a plan but it involves some motion: */ + /* We can make it work but have to plan some motion: */ if (u->elapsed < 0) - return predict_problem(u, t->seg, "arrived but route not set"); + return predict_problem(u, t->seg, "train arriving but route not yet set"); if (t->seg->pred_vacated) { if (!t->seg->now_present) /* And we're not even there yet! This is too hard because we @@ -479,12 +496,10 @@ static int nose_nextseg(TrackLocation *t, TrackAdvanceContext *c, if (!u->train->autopoint || !t->seg->autopoint) 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" + ec= movpos_reserve(t->seg, max_ms, &t->seg->motion_newplan, + route_plan, *mpc_io); + if (ec) return predict_problem(u, t->seg, "insufficient time to" " set route: %s", ec2str(ec)); - - movpos_unreserve(t->seg->motion); - t->seg->motion= route_reservation; *mpc_io= route_plan; movement_ok: @@ -632,6 +647,7 @@ static int optunwind_nextseg(TrackLocation *t, TrackAdvanceContext *c, /*========== prediction entrypoint ==========*/ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, + Segment *desire_move, int desire_movposcomb, PredictionProblemCallback *ppc, void *ppcu) { PredictUserContext u; Segment *foredet; @@ -647,15 +663,22 @@ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, u.stopping= !(flags & PREDF_NEWPLAN) && speedmanager_stopping(u.train); u.stopping_distance= speedmanager_stoppingdistance(u.train, tnow); + u.desire_move= desire_move; + u.desire_movposcomb= desire_movposcomb; + oprintf(DUPO("safety") " predict ***starting*** %s%s maxspeed=%f" - " (speed %f try %f, step %d%s) stopdist=%d flags=%c%c %s\n", + " (speed %f try %f, step %d%s) stopdist=%d flags=%c%c" + " desire=%s/%s %s\n", tra->backwards?"-":"",tra->pname, u.maxspeed, tra->speed.speed, tra->speed.try_speed, tra->speed.step, tra->speed.decel.running ? " decel" : "", u.stopping_distance, "-j"[ !!(flags & PREDF_JUSTDET) ], "-n"[ !!(flags & PREDF_NEWPLAN) ], - u.stopping ? " stopping" : ""); + u.stopping ? " stopping" : "", + u.desire_move ? u.desire_move->i->pname : "", + u.desire_move ? u.desire_move->i->poscombs[u.desire_movposcomb] + .pname : ""); FOR_SEG { seg->det_expected= 0; @@ -801,12 +824,24 @@ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, seg->det_ignore= 0; seg->owner= 0; } - if (seg->motion && !seg->moving && !seg->now_present) { - MovPosChange *reservation= seg->motion; - MovPosComb target= movpos_change_intent(reservation); - seg->motion= 0; - ec= movpos_change(seg, target, -1, reservation); - assert(!ec); + if (seg->motion_newplan == seg->motion) { + seg->motion_newplan= 0; + } else { + if (seg->motion && !seg->moving) { + movpos_unreserve(seg->motion); + seg->motion= 0; + } + if (seg->motion_newplan && !seg->now_present) { + MovPosComb target= movpos_change_intent(seg->motion_newplan); + ec= movpos_change(seg, target, -1, seg->motion_newplan); + assert(!ec); + seg->motion_newplan= 0; + } + if (seg->motion_newplan) { + assert(!seg->motion); + seg->motion= seg->motion_newplan; + seg->motion_newplan= 0; + } } if (u.need_polarise && seg->will_polarise) { seg->seg_inverted= seg->tr_backwards ^ u.train_polarity_inverted; @@ -841,6 +876,13 @@ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, seg->now_present= seg->pred_present= seg->pred_vacated= seg->will_polarise= 0; + if (seg->motion_newplan==seg->motion) { + seg->motion_newplan= 0; + } + if (seg->motion_newplan) { + movpos_unreserve(seg->motion_newplan); + seg->motion_newplan= 0; + } if (!seg->owner && !seg->moving && seg->motion) { movpos_unreserve(seg->motion); seg->motion= 0; @@ -967,7 +1009,7 @@ void safety_notify_detection(Segment *seg) { tra->uncertainty= tra->maxinto= maxinto; report_train_position(tra); - ec= predict(tra,tnow,PREDF_JUSTDET, detection_report_problem, 0); + ec= predict(tra,tnow, PREDF_JUSTDET,0,0, detection_report_problem,0); if (!ec) return; assert(ec == EC_SignallingPredictedProblem); @@ -977,28 +1019,43 @@ void safety_notify_detection(Segment *seg) { report_train_position(tra); speedmanager_safety_stop(tra,tnow); - ec= predict(tra,tnow,PREDF_JUSTDET, 0,(char*)"safety commanding stop"); + ec= predict(tra,tnow, PREDF_JUSTDET,0,0, 0,(char*)"safety commanding stop"); assert(!ec); assert(!ec); } -ErrorCode safety_check_movposchange(Segment *seg, - PredictionProblemCallback *ppc, void *ppcu) { +ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, + int allow_queueing, PredictionProblemCallback *ppc, void *ppcu) { PredictUserContext u; + struct timeval tnow; + ErrorCode ec, ec2; memset(&u,0,sizeof(u)); u.problem_callback= ppc; u.problem_callback_u= ppcu; u.train= seg->owner; - if (seg->owner) { + if (!seg->owner) + return 0; + + if (allow_queueing<2) { if (seg->det_ignore) return predict_problem(&u,seg, " route set for train"); - else - return predict_problem(&u,seg, " route set for approaching train"); + if (seg->det_expected) + return predict_problem(&u,seg, " route set for immiment train"); } - return 0; + if (allow_queueing<1) + return predict_problem(&u,seg, " route set for approaching train"); + + mgettimeofday(&tnow); + ec= predict(seg->owner,tnow, PREDF_NEWPLAN,seg,comb, ppc,ppcu); + if (!ec) return 0; + + ec2= predict(seg->owner,tnow,0, 0,0, 0,(char*)"abandon movposchange"); + assert(!ec2); + + return ec; } void safety_abandon_run(void) { diff --git a/hostside/safety.h b/hostside/safety.h index 2f29077..a7cabf8 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -106,9 +106,13 @@ void safety_setdirection(Train* tra, int backwards); void safety_notify_detection(Segment *seg); /* Called by startup.c when new train detection occurs in state Run. */ -ErrorCode safety_check_movposchange(Segment *seg, - PredictionProblemCallback *ppc, void *ppcu); - /* If this check success, caller may call movpos_change */ +ErrorCode safety_movposchange(Segment *seg, MovPosComb comb, + int allow_queueing, PredictionProblemCallback *ppc, void *ppcu); + /* If this succeeds, caller need not call movpos_change. + * allow_queueing==0 means we only allow unowned segments to move + * ==1 allows changing a segment the train is approaching + * ==2 allows queueing a change for when the train has left + */ #define PREDF_JUSTDET 001u /* we have just detected the train entering its foredetect so we @@ -118,6 +122,7 @@ ErrorCode safety_check_movposchange(Segment *seg, * we are intending to accelerate or change a movpos */ ErrorCode predict(Train *tra, struct timeval tnow, unsigned flags, + Segment *desire_move, int desire_movposcomb, PredictionProblemCallback *ppc, void *ppcu); /* Lower-level interface for speedmanager etc. * Caller must call this with different situations until it succeeds! diff --git a/hostside/speed.c b/hostside/speed.c index 3ed94e8..9341dc7 100644 --- a/hostside/speed.c +++ b/hostside/speed.c @@ -118,7 +118,7 @@ static ErrorCode request_core(Train *tra, int step, struct timeval tnow, toev_start(&tra->speed.decel); tra->speed.speed= vnow; if (ppc || ppcu) { - ec= predict(tra,tnow,0, 0,(char*)"deceleration forbidden"); + ec= predict(tra,tnow, 0,0,0, 0,(char*)"deceleration forbidden"); assert(!ec); } xmit(tra); @@ -126,11 +126,11 @@ static ErrorCode request_core(Train *tra, int step, struct timeval tnow, } tra->speed.try_speed= vtarg; - ec= predict(tra,tnow,PREDF_NEWPLAN, ppc,ppcu); + ec= predict(tra,tnow, PREDF_NEWPLAN,0,0, ppc,ppcu); if (ec) { tra->speed.try_speed= -1; - ec2= predict(tra,tnow,0, 0,(char*)"abandoned acceleration"); + ec2= predict(tra,tnow, 0,0,0, 0,(char*)"abandoned acceleration"); assert(!ec2); return ec; }