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;
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;
};