chiark / gitweb /
allegedly, point setting in train's route
authorian <ian>
Sun, 18 May 2008 01:08:52 +0000 (01:08 +0000)
committerian <ian>
Sun, 18 May 2008 01:08:52 +0000 (01:08 +0000)
hostside/commands.c
hostside/realtime.h
hostside/safety.c
hostside/safety.h
hostside/speed.c

index 244cc87c679f5aea6172724d6ed42eb446abb485..9b1205ced4271b58c9c264a12d77da08de46ddaf 100644 (file)
@@ -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   },
index d405a751dc2609929547b1519533f588b14c7788..f1aa19c21fac93ec0ea3c0ebf48b10386b4f5739 100644 (file)
@@ -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 ----------*/
 
index 0a79b9c90f2aff0dfc6a28046db2275c23424ea3..8c0d1b9d22748785156ba2ef7bc8c96369f1ee04 100644 (file)
@@ -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) {
index 2f290770172f6ba0617579a2b483d460abc04976..a7cabf8d26b2317f9cf89fc04d5d2ae1757fbec9 100644 (file)
@@ -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!
index 3ed94e8c327154b37c87bd814cf8673c73a5373b..9341dc73d1fc71388460e39ed8b8fecac894c503 100644 (file)
@@ -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;
   }