chiark / gitweb /
new safety algorithm wip (previous checkin didn't really have it)
authorian <ian>
Sat, 19 Apr 2008 00:03:07 +0000 (00:03 +0000)
committerian <ian>
Sat, 19 Apr 2008 00:03:07 +0000 (00:03 +0000)
hostside/TODO
hostside/safety.c
hostside/safety.h

index f6da014be3127fe30a33842054c595f91d69f7da..1f45ac7da4bc4fcb6547404975354b60ec94e134 100644 (file)
@@ -1,3 +1,6 @@
+either only POLARITY when we've had POLARISED or delete
+ that bit from the docs
+
 
 
 with santafe at X8, we get this:
index 13d1a1f1bfa8db6201311d03012683497e5b4477..2ae6eda8491479e76a3cd79152a9e47e42275028 100644 (file)
@@ -12,6 +12,129 @@ int n_trains;
 Train *trains;
 Segment *segments;
 
+
+
+/*
+ * New signalling/safety algorithm:
+ *
+ * When we detect a train at the relevant det_expected we firstly
+ * update our knowledge of its current position.  We don't change
+ * any ownerships just yet, but we do set pred_present for the parts
+ * where the train is right now.
+ *
+ * We then check to see that when we reach the _next_ block boundary,
+ * we'll still be able to stop safely (unless we're already doing an
+ * emergency stop).  If this fails we issue the emergency stop command
+ * now.  This prediction is done as follows:
+ *
+ * We use three tracklocs which move in step - one for the foredetect
+ * and one for each end of our train.  This represents a predicted
+ * train position.  (We use `predicted' to refer to these future
+ * situations and `current' to refer to that prevailing at the time we
+ * are making the prediction.)  When we advance these we advance
+ * the head and foredetect in lockstep; when the foredetect enters
+ * a new segment we chase up the with the tail.
+ *
+ * We advance these tracklocs firstly exactly one segment and then
+ * over the current stopping distance.  At each advancement we record
+ * the time from the currently-next detection at which this prediction
+ * will happen (computed from the current speed).  (We don't take into
+ * account any already commanded but not necessarily happened
+ * deceleration; however if we are attempting to increase our speed,
+ * current speed refers to the new speed.)  If we're already emergency
+ * stopping then we ignore the stopping distance and instead keep
+ * advancing until we run out of segments we own.
+ *
+ * At each new track location for our front end we hope to find a
+ * segment which no-one currently owns and which is currently set for
+ * us.  (We check this before updating our tail trackloc as below.)
+ * In that case we update the segment's until_here.
+ *
+ * However it may be a segment which we currently own, or perhaps it
+ * may be set against us.  (If it's owned by anyone else or is not
+ * owned but moving then we are definitely doomed and must stop.)
+ *
+ * If it's owned by us but we haven't claimed it yet in this
+ * prediction then that's fine we can just claim it.
+ *
+ * If we _have_ claimed it then it had better be predicted to be
+ * vacant by the time we get there (pred_vacant set, see below).
+ *
+ * If it is currently moving then that must be OK because we checked
+ * it before (except that if we're trying to increase our speed that
+ * may not be OK and we must reject the speed increase because we
+ * can't easily check whether the movement would happen in time).
+ *
+ * If it is not currently moving and is set against us, then we need
+ * to arrange that we set it appropriately: if we've just claimed the
+ * segment then we can ask movfeat to set it for us (using any
+ * reservation which we may have stashed away) (and fail if it
+ * declines); otherwise we ask movfeat to give us a reservation valid
+ * for the time interval between the predicted vacation and present
+ * times.
+ *
+ * When predicted foredetect enters a new segment we add the new
+ * segment to the tally of segments of the particular kind and
+ * train-relative orientation (for polarity purposes), and check that
+ * a solution is possible.  For the first such solution (ie, the one
+ * for the immediately-forthcoming detection) we actually implement
+ * it.
+ *
+ * And, when predicted foredetect enters a new segment we advance the
+ * predicted tail (as described above).  We set pred_vacated and
+ * until_here, and remove the departing segments from the kind and
+ * train-relative orientation tallies.
+ *
+ * If all of this works then pred_present and pred_vacated constitute
+ * the new ownership.
+ *
+ * If not then we issue an signal stop command (we'd better not be
+ * doing that already!) or countermand the speed increase or whatever */
+
+ * Having advanced the head, we 
+
+ owner         train which owns this for signalling purposes
+               no other train may interfere
+
+ physical      in an unowned segment, this has no particular
+ feature               relationship to anything
+  &
+ movposcomb    in an owned segment, if moving, means that
+  &                    we have a promise that the feature
+ moving                        will be OK by the time we get there
+                       at our current speed
+
+ move_reservation
+               0 for unowned segments (although during prediction
+                       may be non-0 for a bit, in which case
+                       we garbage collect it in a bit)
+
+               for an owned segment is our reservation which
+                       allows us to know that we are going to
+                       be able to change this segment between
+                       the tail leaving it and the head arriving
+
+ det_ignore    we expect interference detection here due to a crossing
+                       (unowned segment)
+               or this is part of the body of a train which we've
+                       already detected here (owned segment)
+
+ det_expected  this is the next place we expect owner train to arrive
+               (it is not valid to have both det_ignore and _expected)
+
+VALID DURING PREDICTION ETC. ONLY
+
+ pred_present  in our prediction, the train physically occupies this
+               until_here tells us when will be
+
+ pred_vacated   in our prediction, the train does not occupy this
+                       although it did in previous predictions
+               until_here tells us when it will have been vacated
+               if set together with pred_present, means was vacated
+                       and then reentered; do not record vacation again
+
+/* ============ OLD CODE ========== */
+
 static void seg_clear_stale(Segment *seg) {
   seg->owner= 0;
   seg->until_here= seg->until_detect= 0;
index 2dcb0c6838f3678dff6628f1c0f277a590cd30ad..f99f12b7ae83d6e6726caeff10d6e5dcc48e18fd 100644 (file)
@@ -69,12 +69,16 @@ struct Segment {
     ho_backwards:1, /* home train has its front and rear backwards wrt track */
     cm_autostop:1, /* train should stop on detection */
     seg_inverted:1, /* polarity is inverted */
-    tr_updated:1, /* for use by safety.c:lay_train etc.; otherwise 0 */
+    det_ignore:1,
+    det_expected:1,
+    pred_enter:1, /* for use by safety.c:lay_train etc.; otherwise 0 */
+    pred_vacate:1, /* for use by safety.c:lay_train etc.; otherwise 0 */
     res_detect:1; /* detection noticed here during resolution */
-  TimeInterval until_here, /* ) nonnegative; */  /* ) always valid but      */
-    until_detect;          /* ) 0 if already */  /* )  meaningful iff owner */
+  TimeInterval until_here; /* ) nonnegative; */  /* ) always valid but      */
+                           /* ) 0 if already */  /* )  meaningful iff owner */
   MovPosComb movposcomb; /* -1 means not known or moving */
-  MovPosChange *moving; /* non-0 iff feature(s) have been told to change */
+  MovPosChange *moving, /* non-0 iff feature(s) have been told to change */
+    *move_reservation;  /* see safety.c */
   const SegmentInfo *i;
 };