From ea42cc143ca9966639ef785606b78ecc92c28aed Mon Sep 17 00:00:00 2001 From: ian Date: Sat, 19 Apr 2008 00:03:07 +0000 Subject: [PATCH] new safety algorithm wip (previous checkin didn't really have it) --- hostside/TODO | 3 ++ hostside/safety.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++ hostside/safety.h | 12 +++-- 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/hostside/TODO b/hostside/TODO index f6da014..1f45ac7 100644 --- a/hostside/TODO +++ b/hostside/TODO @@ -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: diff --git a/hostside/safety.c b/hostside/safety.c index 13d1a1f..2ae6eda 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -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; diff --git a/hostside/safety.h b/hostside/safety.h index 2dcb0c6..f99f12b 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -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; }; -- 2.30.2