chiark / gitweb /
safety_setdirection compiles but untested
authorian <ian>
Wed, 16 Jul 2008 20:37:14 +0000 (20:37 +0000)
committerian <ian>
Wed, 16 Jul 2008 20:37:14 +0000 (20:37 +0000)
hostside/safety.c
hostside/safety.h
hostside/speed.c

index 0b2a8d46ee0650f2073a00efa89d3d02c0f26c20..9c3a10f9c2c08a30fe83a96c04317c1428c30245 100644 (file)
@@ -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;
 
index 1f1fdafda92181eeced49fb094e896f4f9a55fd2..1a74fe084c708b02fa4bd6746ebd674f137b752e 100644 (file)
@@ -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);
 
index 305b2d02c77654daf3a3e5bb0b22bc8d4b9056d7..a405b29a450acaa49977a3fdd29dfab9ae237a79 100644 (file)
@@ -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);
 }