From: ian Date: Sat, 26 Apr 2008 22:59:52 +0000 (+0000) Subject: many bugfixes; working on resolution X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=61e7203d7fcd07a2ef6f99a27bceb8e823cb2cc2;p=trains.git many bugfixes; working on resolution --- diff --git a/hostside/README.commands b/hostside/README.commands index c4e60c8..d26aa97 100644 --- a/hostside/README.commands +++ b/hostside/README.commands @@ -34,6 +34,7 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC U< resolving U< resolution inexplicable + U< resolution mispositioned U< resolution movpos-change-failed / U< resolution problems @@ -71,7 +72,9 @@ COMMANDS AND RESPONSES then one of these R< ack ok R< ack - R< ack : ... + R< ack [] : ... + R< ack SignallingPredictedProblem \ + |? : ... ====================================================================== diff --git a/hostside/TODO b/hostside/TODO index 8e6f926..6f19047 100644 --- a/hostside/TODO +++ b/hostside/TODO @@ -6,6 +6,10 @@ bugs possible can we fail resolution at this point ? + does not set serial port mode etc. + multiple motions handling is wrong: deadline miscalculated etc. + deadline should be start deadline and we should sub length + want to document commands [!]movfeat and speed stop all trains command ? diff --git a/hostside/commands.c b/hostside/commands.c index dff8535..6066bff 100644 --- a/hostside/commands.c +++ b/hostside/commands.c @@ -30,7 +30,9 @@ struct ManualRetransmitNode { static void cmd_ppc(Train *tra, Segment *seg, void *pu, const char *message) { const CmdInfo *ci= pu; - oprintf(UPO,"ack %s SignallingPredictedProblem : %s", ci->name, message); + oprintf(UPO,"ack %s SignallingPredictedProblem %s %s : %s", + ci->name, + tra->pname, seg ? seg->i->pname : "?", message); } #define MUSTECRPREDICT(requester) do{ \ diff --git a/hostside/movpos.c b/hostside/movpos.c index e682abe..24f9143 100644 --- a/hostside/movpos.c +++ b/hostside/movpos.c @@ -262,7 +262,7 @@ static ErrorCode pt_check_plan(void) { for (;;) { PointReq *confr= conf < pt_confirmed.n ? pt_confirmed.l[conf] : 0; - PointReq *resvr= resv < pt_reserved .n ? pt_reserved .l[conf] : 0; + PointReq *resvr= resv < pt_reserved .n ? pt_reserved .l[resv] : 0; if (!confr && !resvr) break; oprintf(UPO," %d:",future); int confwhen= confr ? confr->deadline - pt_cslot : INT_MAX; diff --git a/hostside/resolve.c b/hostside/resolve.c index bda9b47..6d9c799 100644 --- a/hostside/resolve.c +++ b/hostside/resolve.c @@ -1,171 +1,161 @@ /* * resolve detected trains into initial state */ -/* - * Algorithm: - * - * Notation and background: - * - * S set of segments - * D \subset S set of segments where we have detection - * - * T set of trains - * H(t) \subset S home range for train t \elem T - * E(t) \subset S set of segments where train t last expected - * - * H(t) \disjoint H(t') for t != t' - * E(t) \disjoint E(t') for t != t' - * but not necessarily E(t) \disjoint H(t') - * - * We want to find a mapping R(t) - * R(t) \elem { N, E, H } t \elem T, N(t') = \null - * giving - * A(t) = (R(t))(t) segments allocated to train t - * U = \union_{t} A(t) - * satisfing - * A(t) \disjoint A(t') for t != t' `disjoincy' - * D \subset U `coverage' - * and the solution is somehow optimal or at least not badly suboptimal. - * - * We compute R incrementally, maintaining disjoincy,, - * while increasing U. At each stage R is an optimal solution - * to the problem posed by D' = U, and we maintain this invariant. - * - * We define an optimality ordering on R by counting occurrences of - * H, E, and H in the range, in that order. Ie, - * Count(R,x) = |{ t: R(t) = x }| - * Rank(R) = Count(R,H) * (|T|+1) + Count(R,E) - * and compare Ranks numerically, lower being better. - * - * So we mean that for any incrementally computed R, there is no - * R' satisfying the same subproblem D' = U for which Rank(R') < Rank(R). - * - * For the benefit of client programs, we record the key elements of - * the proofs that we generate for non-N values of R. - * - * 1. Initially we set \all_{t} R(t) = N. - * - * Optimality: This is minimal for U = \null, as Rank(R) = 0. - * - * 2. Then we search for lack of coverage, ie violations of D \subset U. - * If none are found we are done. - * - * 3. Let d \elem D but d !\elem U. - * We will now calculate new R which we will call R2 - * giving new U which we will call U2. - * - * 3a. Hope that \exists{t} st d \elem E(t) with - * E(t) \disjoint U and R(t) = N. - * If so set R2(t) = E giving a solution to U2. - * - * Optimality: if d \elem D then we need U2 to include d. - * That means d \elem E(t) or d \elem H(t'). No E(t') - * other than E(t) can help since they are disjoint, and - * we would certainly prefer adding E(t) to adding H(t'). - * (Adding H(t') and removing some other H(t'') doesn't - * work either because the Hs are disjoint, so no - * H can stand in for any other.) - * - * So the rank increase by 1 is is minimal for U2. - * - * Proof elements: R(t) = E is demonstrated by - * every d meeting these conditions. - * - * 3b. Alternatively, hope that d \elem H(t') - * - * If so set R2(t') = H - * \all_{t+} R2(t+) = N where R(t+) = E. - * - * Optimality: in the case we are now dealing with, we - * didn't succeed with the test for 3a, so either: - * - * (i) There is no t where d \elem E(t), so R(t') = H is - * essential because no solution without R(t') = H has d \elem U2. - * - * (ii) There is t where d \elem E(t) but R(t) = H. - * We have therefore already proved that R(t) cannot be E. - * - * (iii) There is t where d \elem E(t) but E(t) !\disjoint U - * In this case, consider a clash d' between E(t) and U - * d' \elem U, d' \elem E(t) - * - * This clash at d' is preventing us covering d with E(t). - * E's can't clash since they are disjoint so it must be - * a clash with some H. But we have no unavoidable H's - * in our solution to U, so this solution to U2 has no - * unavoidable H's either. - * - * Or to put it algebraically, - * d' != d, because d !\elem U. - * d' \elem A(t'') for some t'' since d' \elem U. - * If R(t'') = E, d' \elem E(t'') but E's are disjoint. - * So R(t'') = H, which must have been unavoidable by our - * inductive premise. Thus for U2, R2(t'') = H is also - * unavoidable. - * - * Proof elements: R(t') = H is demonstrated by - * every d meeting these conditions - * together with for each such d - * the alternative train t if applicable - * (there can be only one) - * plus in case (iii) - * every clash d' between E(t) and U - * plus for each such d' the corresponding t'' - * (we record all this indexed by t so we can reuse it - * if needed) - * - * R2 consists only of Hs and Ns. All of the Hs are necessary - * for U2 by the above, so R2 is minimal for U2. - * - * The rank is increased: we increase Count(R,H) and set - * Count(R,E) to 0. - * - * 3c. If neither of these is true, we are stuck and cannot - * satisfy d. This is an error. We remove d from D - * and continue anyway to see if we can find any more. - * - * Proof elements: Lack of solution is demonstrated - * separately by every such d together with - * for each d if d \elem E(t) for some t - * that t - * plus the clashes d'' as for 3b(iii). - * - * Termination: at each iteration 3a or 3b, we strictly increase Rank. - * At each iteration 3c we reduce D. - * Rank cannot exceed |T|*(|T|+1) and D starts out finite. So - * eventually we must succeed or fail. - * - */ #include "realtime.h" +#define NOOP (void)0 + +/*---------- main resolution processing ----------*/ + /* + * Algorithm: + * + * Notation and background: + * + * S set of segments + * D \subset S set of segments where we have detection + * + * T set of trains + * H(t) \subset S home range for train t \elem T + * E(t) \subset S set of segments where train t last expected + * + * H(t) \disjoint H(t') for t != t' + * E(t) \disjoint E(t') for t != t' + * but not necessarily E(t) \disjoint H(t') + * + * We want to find a mapping R(t) + * R(t) \elem { N, E, H } t \elem T, N(t') = \null + * giving + * A(t) = (R(t))(t) segments allocated to train t + * U = \union_{t} A(t) + * satisfing + * A(t) \disjoint A(t') for t != t' `disjoincy' + * D \subset U `coverage' + * and the solution is somehow optimal or at least not badly suboptimal. + * + * We compute R incrementally, maintaining disjoincy,, + * while increasing U. At each stage R is an optimal solution + * to the problem posed by D' = U, and we maintain this invariant. + * + * We define an optimality ordering on R by counting occurrences of + * H, E, and H in the range, in that order. Ie, + * Count(R,x) = |{ t: R(t) = x }| + * Rank(R) = Count(R,H) * (|T|+1) + Count(R,E) + * and compare Ranks numerically, lower being better. + * + * So we mean that for any incrementally computed R, there is no + * R' satisfying the same subproblem D' = U for which Rank(R') < Rank(R). + * + * For the benefit of client programs, we record the key elements of + * the proofs that we generate for non-N values of R. + * + * 1. Initially we set \all_{t} R(t) = N. + * + * Optimality: This is minimal for U = \null, as Rank(R) = 0. + * + * 2. Then we search for lack of coverage, ie violations of D \subset U. + * If none are found we are done. + * + * 3. Let d \elem D but d !\elem U. + * We will now calculate new R which we will call R2 + * giving new U which we will call U2. + * + * 3a. Hope that \exists{t} st d \elem E(t) with + * E(t) \disjoint U and R(t) = N. + * If so set R2(t) = E giving a solution to U2. + * + * Optimality: if d \elem D then we need U2 to include d. + * That means d \elem E(t) or d \elem H(t'). No E(t') + * other than E(t) can help since they are disjoint, and + * we would certainly prefer adding E(t) to adding H(t'). + * (Adding H(t') and removing some other H(t'') doesn't + * work either because the Hs are disjoint, so no + * H can stand in for any other.) + * + * So the rank increase by 1 is is minimal for U2. + * + * Proof elements: R(t) = E is demonstrated by + * every d meeting these conditions. + * + * 3b. Alternatively, hope that d \elem H(t') + * + * If so set R2(t') = H + * \all_{t+} R2(t+) = N where R(t+) = E. + * + * Optimality: in the case we are now dealing with, we + * didn't succeed with the test for 3a, so either: + * + * (i) There is no t where d \elem E(t), so R(t') = H is + * essential because no solution without R(t') = H has d \elem U2. + * + * (ii) There is t where d \elem E(t) but R(t) = H. + * We have therefore already proved that R(t) cannot be E. + * + * (iii) There is t where d \elem E(t) but E(t) !\disjoint U + * In this case, consider a clash d' between E(t) and U + * d' \elem U, d' \elem E(t) + * + * This clash at d' is preventing us covering d with E(t). + * E's can't clash since they are disjoint so it must be + * a clash with some H. But we have no unavoidable H's + * in our solution to U, so this solution to U2 has no + * unavoidable H's either. + * + * Or to put it algebraically, + * d' != d, because d !\elem U. + * d' \elem A(t'') for some t'' since d' \elem U. + * If R(t'') = E, d' \elem E(t'') but E's are disjoint. + * So R(t'') = H, which must have been unavoidable by our + * inductive premise. Thus for U2, R2(t'') = H is also + * unavoidable. + * + * Proof elements: R(t') = H is demonstrated by + * every d meeting these conditions + * together with for each such d + * the alternative train t if applicable + * (there can be only one) + * plus in case (iii) + * every clash d' between E(t) and U + * plus for each such d' the corresponding t'' + * (we record all this indexed by t so we can reuse it + * if needed) + * + * R2 consists only of Hs and Ns. All of the Hs are necessary + * for U2 by the above, so R2 is minimal for U2. + * + * The rank is increased: we increase Count(R,H) and set + * Count(R,E) to 0. + * + * 3c. If neither of these is true, we are stuck and cannot + * satisfy d. This is an error. We remove d from D + * and continue anyway to see if we can find any more. + * + * Proof elements: Lack of solution is demonstrated + * separately by every such d together with + * for each d if d \elem E(t) for some t + * that t + * plus the clashes d'' as for 3b(iii). + * + * Termination: at each iteration 3a or 3b, we strictly increase Rank. + * At each iteration 3c we reduce D. + * Rank cannot exceed |T|*(|T|+1) and D starts out finite. So + * eventually we must succeed or fail. + * + */ + /* values for Train->resolution: */ #define RR_N 0u #define RR_E 1u #define RR_H 2u +#define RESOLUTION_CHARS "NEH" -/* We record R in tra->resolution, - * U in segi->mark0 and D in segi->res_detect */ +/* During the main algorithm: + * We record R in tra->resolution, + * U in segi->mark0 and D in segi->res_detect + */ #define iselem_u mark0 -#define resfin_done mark0 - -void resolve_begin(void) { - SEG_IV; - actual_inversions_start(); - FOR_SEG { - seg->res_detect= 0; - seg->iselem_u= 0; - if (segi->invertible) - actual_inversions_segment(seg); - else - seg->seg_inverted= 0; - } - actual_inversions_done(); -} - -#define NOOP (void)0 -int resolve_complete(void) { +static int resolve_complete_main(void) { int problems, phase, nextphase; TRAIN_ITERVARS(t); TRAIN_ITERVARS(t2); @@ -188,7 +178,7 @@ int resolve_complete(void) { #define ADDTO_U_EH(homeowner,HH_HE,string) \ if (d->homeowner && d->homeowner->resolution == HH_HE) { \ - oprintf(DUPO("resolving") " covered @%s " string " %s\n", \ + oprintf(DUPO("resolving") " covered %s " string " %s\n", \ di->pname, d->homeowner->pname); \ updated++; \ } @@ -297,7 +287,7 @@ int resolve_complete(void) { if (phase<2) continue; - oprintf(UPO, "resolution inexplicable @%s\n", di->pname); + oprintf(UPO, "resolution inexplicable %s\n", di->pname); d->res_detect= 0; problems++; } @@ -305,25 +295,25 @@ int resolve_complete(void) { FOR_SEGMENT(d,NOOP,NOOP) { if (problems) - goto x_problems; + return problems; d->iselem_u= 0; MovPosComb target= -1; if (d->home && d->home->resolution == RR_H) { - d->owner= d->home; d->tr_backwards= d->ho_backwards; target= 0; /* a bit kludgey */ } else if (d->owner) { d->tr_backwards ^= d->owner->backwards; target= d->movposcomb; - } + } if (d->i->n_poscombs>1) { d->movposcomb= -1; if (target >= 0) { - ErrorCode ec= movpos_change(d,target,-1,0); + assert(!d->motion); + ErrorCode ec= movpos_reserve(d,-1,&d->motion,target,-1); if (ec) { oprintf(UPO, "resolution movpos-change-failed %s/%s %s\n", d->i->pname, d->i->poscombs[target].pname, @@ -336,18 +326,15 @@ int resolve_complete(void) { d->movposcomb= 0; } } + return problems; +} - if (problems) { - x_problems: - oprintf(UPO,"resolution problems %d\n",problems); - return -1; - } +#undef iselem_u - FOR_TRAIN(t,NOOP,NOOP) - speedmanager_reset_train(t); +/*---------- heads and tails of trains, final placement ----------*/ - return 0; -} +#define resfin_ours mark1 +#define resfin_done mark2 typedef struct { Train *train; @@ -355,58 +342,98 @@ typedef struct { int extraspace; } FindEndUserContext; +static int findends_getmovpos(TrackLocation *t, TrackAdvanceContext *c, + MovPosComb *use_io) { + const char *pn= t->seg->i->pname; + if (t->seg->motion) *use_io= movpos_change_intent(t->seg->motion); + if (*use_io<0) { + oprintf(DUPO("resolving") " ends getmovpos %s fails\n", pn); + return -1; + } +// oprintf(DUPO("resolving") " ends getmovpos %s -> %d\n", pn, *use_io); + return 0; +} + static int segdist(Segment *seg) { - assert(seg->movposcomb >= 0); - return seg->i->poscombs[seg->movposcomb].dist; + TrackLocation t; + int r; + MovPosComb mpc; + + t.seg= seg; + mpc= seg->movposcomb; + + r= findends_getmovpos(&t,0,&mpc); + assert(!r); assert(mpc >= 0); + return seg->i->poscombs[mpc].dist; } -static void finalise_callback_debug(const char *what, TrackLocation *t, - struct TrackAdvanceContext *c) { - oprintf(DUPO("resolving") " finalise %s" - " %s%s owner=%s res_detect=%d resfin_done=%d\n", +static void ends_callback_debug(const char *what, TrackLocation *t, + struct TrackAdvanceContext *c) { + oprintf(DUPO("resolving") " ends %s" + " %s%s det=%d ours=%d done=%d owner=%s home=%s\n", what, t->backwards?"-":"", t->seg->i->pname, - t->seg->owner ? t->seg->owner->pname : "0", - t->seg->res_detect, t->seg->resfin_done); + t->seg->res_detect, + t->seg->resfin_ours, + t->seg->resfin_done, + t->seg->owner ? t->seg->owner->pname : "-", + t->seg->home ? t->seg->home->pname : "-"); } static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { FindEndUserContext *u= c->u; - finalise_callback_debug("findhead_nextseg",t,c); + ends_callback_debug("findhead_nextseg",t,c); - if (t->seg->owner != u->train) return -1; + if (!t->seg->resfin_ours || t->seg->resfin_done) return -1; u->furthest= t->seg; if (!t->seg->res_detect) { u->extraspace= 0; return -1; } u->train->foredetect= t->seg; t->seg->tr_backwards= t->backwards; - t->seg->res_detect= 0; + t->seg->resfin_done= 1; return 0; } static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, MovPosComb *mpc_io, Segment *before) { - FindEndUserContext *u= c->u; - - finalise_callback_debug("walkback_nextseg",t,c); + ends_callback_debug("walkback_nextseg",t,c); - if (t->seg->owner != u->train) return -1; + if (!t->seg->resfin_ours) return -1; t->seg->tr_backwards= !t->backwards; t->seg->resfin_done= 1; return 0; } -static void resolve_train_finalise(Segment *startpoint) { +static int resolve_complete_ends_train(Train *tra) { SEG_IV; - Train *tra; TrackLocation t; TrackAdvanceContext tc; FindEndUserContext u; int r; + Segment *startpoint; - assert(startpoint->owner); - tra= startpoint->owner; + switch (tra->resolution) { + case RR_H: break; + case RR_E: break; + case RR_N: return 0; + default: abort(); + } + + oprintf(DUPO("resolving") " ends %s %c\n", + tra->pname, RESOLUTION_CHARS[tra->resolution]); + + startpoint= 0; + + FOR_SEGMENT(seg,NOOP,NOOP) { + seg->resfin_done= 0; + seg->resfin_ours= tra == + (tra->resolution==RR_H ? seg->home : seg->owner); + if (seg->resfin_ours && seg->res_detect) + startpoint= seg; + } + + assert(startpoint); t.seg= startpoint; t.remain= 0; @@ -416,34 +443,30 @@ static void resolve_train_finalise(Segment *startpoint) { tc.distance= TL_DIST_INF; tc.nextseg= findhead_nextseg; + tc.getmovpos= findends_getmovpos; tc.trackend= 0; - tc.getmovpos= 0; tc.u= &u; u.train= tra; u.extraspace= MARGIN_NOSE + tra->head; u.furthest= 0; - oprintf(DUPO("resolving") " finalise %s start=%s%s es=%d\n", - tra->pname, - t.backwards?"-":"", t.seg->i->pname, - u.extraspace); + oprintf(DUPO("resolving") " ends start=%s%s es=%d\n", + t.backwards?"-":"", t.seg->i->pname, u.extraspace); r= findhead_nextseg(&t,&tc,0,0); assert(!r); trackloc_advance(&t,&tc); - oprintf(DUPO("resolving") " finalise es=%d furthest=%s fdd(%s)=%d\n", + oprintf(DUPO("resolving") " ends es=%d furthest=%s fd=%s%s fd.dist=%d\n", u.extraspace, u.furthest->i->pname, - tra->foredetect->i->pname, segdist(tra->foredetect)); + tra->foredetect->tr_backwards?"-":"", tra->foredetect->i->pname, + segdist(tra->foredetect)); tra->maxinto= segdist(tra->foredetect) - u.extraspace; if (tra->maxinto < 0) tra->maxinto= 0; tra->uncertainty= tra->maxinto; - FOR_SEG { - if (seg->owner == tra) seg->res_detect= 0; - seg->resfin_done= 0; - } + FOR_SEG seg->resfin_done= 0; t.seg= tra->foredetect; t.remain= segdist(tra->foredetect) - u.extraspace; @@ -455,15 +478,17 @@ static void resolve_train_finalise(Segment *startpoint) { r= walkback_nextseg(&t,&tc,0,0); assert(!r); trackloc_advance(&t,&tc); - oprintf(DUPO("resolving") " finalise maxi=%d unc=%d;" + oprintf(DUPO("resolving") " ends maxi=%d unc=%d;" " remaining distance=%d\n", tra->maxinto, tra->uncertainty, tc.distance); if (tc.distance) { tra->uncertainty -= tc.distance; - if (tra->uncertainty < 0) - safety_panic(tra, t.seg, "resolved train location too small by %d!", - -tra->uncertainty); + if (tra->uncertainty < 0) { + oprintf(UPO, "resolution mispositioned %s %s -%d\n", + tra->pname, t.seg->i->pname, -tra->uncertainty); + return 1; + } } FOR_SEG { @@ -477,9 +502,70 @@ static void resolve_train_finalise(Segment *startpoint) { } report_train_position(tra); - report_train_ownerships(tra, u.furthest); + report_train_ownerships(tra, u.furthest, 0); + + return 0; +} + +static int resolve_complete_ends(void) { + TRA_IV; + int problems; + + problems= 0; + FOR_TRAIN(tra,NOOP,NOOP) + problems += resolve_complete_ends_train(tra); + return problems; +} + +#undef resfin_ours +#undef resfin_done + +/*---------- main resolutionentrypoints ----------*/ + +void resolve_begin(void) { + SEG_IV; + actual_inversions_start(); + FOR_SEG { + seg->res_detect= 0; + if (segi->invertible) + actual_inversions_segment(seg); + else + seg->seg_inverted= 0; + } + actual_inversions_done(); +} + +int resolve_complete(void) { + int problems; + ErrorCode ec; + TRA_IV; + SEG_IV; + + problems= resolve_complete_main(); + if (!problems) + problems += resolve_complete_ends(); + + if (problems) { + oprintf(UPO,"resolution problems %d\n",problems); + return -1; + } + + FOR_SEG { + if (seg->owner && seg->owner->resolution == RR_N) + seg->owner= 0; + + MovPosChange *reservation= seg->motion; + if (!reservation) continue; + seg->motion= 0; + MovPosComb target= movpos_change_intent(reservation); + ec= movpos_change(seg, target, -1, reservation); assert(!ec); + } + + FOR_TRA + speedmanager_reset_train(tra); + + return 0; } - void resolve_motioncheck(void) { SEG_IV; @@ -488,9 +574,5 @@ void resolve_motioncheck(void) { FOR_SEG if (seg->moving) return; - FOR_SEG - if (seg->res_detect) - resolve_train_finalise(seg); - sta_finalising_done(); } diff --git a/hostside/safety.c b/hostside/safety.c index c9be91b..4d23487 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -235,6 +235,7 @@ typedef struct { count_time:1, accelerating:1, usecurrentposn:1, /* for pred_getmovpos */ + forceusemotions:1, /* for report_train_ownerships only */ walk_compute_polarise:1, /* nose_nextseg still needs to worry */ need_polarise:1, /* when we commit */ train_polarity_inverted:1, /* right now, or if know_best, the best */ @@ -532,7 +533,7 @@ static int fdet_nextseg(TrackLocation *t, TrackAdvanceContext *c, /*---------- reporting position and ownership ----------*/ void report_train_position(Train *tra) { - oprintf(UPO, "train %s %s at %s%s:%d+-%d", + oprintf(UPO, "train %s %s at %s%s:%d+-%d\n", tra->pname, tra->backwards ? "backwards" : "forwards", tra->foredetect->tr_backwards?"-":"", tra->foredetect->i->pname, tra->maxinto, tra->uncertainty); @@ -550,11 +551,13 @@ static int report_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, * head is going to be in the far future. Confusing, eh ? */ return -1; + flags[0]= 0; + if (t->seg->det_expected) strcat(flags,"*"); if (t->seg == u->train->foredetect) { strcat(flags,"!"); - u->usecurrentposn=1; + u->usecurrentposn=u->forceusemotions; } if (t->seg->det_ignore) strcat(flags,"@"); @@ -564,14 +567,15 @@ static int report_nextseg(TrackLocation *t, struct TrackAdvanceContext *c, oprintf(UPO," %s%s",flags,t->seg->i->pname); if (t->seg->i->n_poscombs > 1) { - r= pred_getmovpos(t,c,mpc); assert(!r); + r= pred_getmovpos(t,c,mpc); assert(!r); assert(*mpc>=0); oprintf(UPO,"/%s", t->seg->i->poscombs[*mpc].pname); } return 0; } -void report_train_ownerships(Train *tra, Segment *furthest) { +void report_train_ownerships(Train *tra, Segment *furthest, + int force_use_motions) { PredictUserContext u; MovPosComb mpc; int r; @@ -580,6 +584,7 @@ void report_train_ownerships(Train *tra, Segment *furthest) { u.train= tra; u.furthest= furthest; u.usecurrentposn= 0; + u.forceusemotions= force_use_motions; /* Walk backwards along the train printing its segments: */ oprintf(UPO, "train %s has", tra->pname); @@ -609,6 +614,11 @@ ErrorCode predict_confirm(Train *tra, int accelerate, SEG_IV; ErrorCode ec; + memset(&u,0,sizeof(u)); + u.train= tra; + u.problem_callback= ppc; + u.problem_callback_u= ppcu; + FOR_SEG { seg->now_present= seg->pred_present= seg->pred_vacated= seg->will_polarise= 0; @@ -616,13 +626,12 @@ ErrorCode predict_confirm(Train *tra, int accelerate, foredet= tra->foredetect; - memset(&u,0,sizeof(u)); - u.train= tra; + if (!foredet) + return predict_problem(&u,0,"train is not on layout"); + u.accelerating= accelerate; u.walk_compute_polarise= 1; u.train_polarity_inverted= foredet->seg_inverted ^ foredet->tr_backwards; - u.problem_callback= ppc; - u.problem_callback_u= ppcu; u.furthest= tra->foredetect; u.usecurrentposn= 1; @@ -705,7 +714,7 @@ ErrorCode predict_confirm(Train *tra, int accelerate, if (u.need_polarise) actual_inversions_done(); - report_train_ownerships(tra,u.furthest); + report_train_ownerships(tra,u.furthest,0); return 0; xproblem: diff --git a/hostside/safety.h b/hostside/safety.h index 1c4c474..eb9bec5 100644 --- a/hostside/safety.h +++ b/hostside/safety.h @@ -116,7 +116,8 @@ ErrorCode predict_confirm(Train *tra, int accelerate, */ void report_train_position(Train *tra); -void report_train_ownerships(Train *tra, Segment *furthest); +void report_train_ownerships(Train *tra, Segment *furthest, + int force_use_motions); /* ... for use by things which update these only, which * is basically safety.c and resolve.c */ diff --git a/hostside/trackloc.c b/hostside/trackloc.c index 3305861..58384b6 100644 --- a/hostside/trackloc.c +++ b/hostside/trackloc.c @@ -45,12 +45,16 @@ int trackloc_getlink(TrackLocation *t, TrackAdvanceContext *c, if (r) return r; } if (mpc<0) { - *pci_r=0; - *link_r=0; + if (pci_r) *pci_r=0; + if (link_r) *link_r=0; return 0; } + assert(mpc >= 0); assert(mpc < t->seg->i->n_poscombs); - pci= &t->seg->i->poscombs[t->seg->movposcomb]; +//fprintf(stderr,"trackloc_getlink returning %s %d %d\n",t->seg->i->pname,mpc, +// t->backwards); + pci= &t->seg->i->poscombs[mpc]; +//fprintf(stderr,"trackloc_getlink returning %s\n",pci->pname); if (pci_r) *pci_r= pci; if (link_r) *link_r= &pci->link[t->backwards]; return 0; @@ -66,8 +70,12 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { MovPosComb mpc_nego; int r; - r= trackloc_getlink(t,c, 0,&link, t->seg->movposcomb); + r= trackloc_getlink(t,c, &pci,&link, t->seg->movposcomb); if (r || !link) return r; +//fprintf(stderr,"advance start getlink %s%s/%s -> %s\n", +// t->backwards?"-":"", t->seg->i->pname, +// pci ? pci->pname : "?", +// link && SOMEP(link->next) ? info_segments[link->next].pname : "?"); for (;;) { if (!c->distance) return 0; @@ -99,6 +107,10 @@ int trackloc_advance(TrackLocation *t, TrackAdvanceContext *c) { r= trackloc_getlink(t,c, &pci,&link, mpc_nego); if (r || !link) return r; +//fprintf(stderr,"advance ran getlink %s/%s -> %s\n",leaving->i->pname, +// pci ? pci->pname : "?", +// link && SOMEP(link->next) ? info_segments[link->next].pname : "?"); + t->remain= pci->dist; } } diff --git a/hostside/x.gdb b/hostside/x.gdb index a393f9f..c196412 100644 --- a/hostside/x.gdb +++ b/hostside/x.gdb @@ -11,4 +11,5 @@ break safety_panic run -# strace -e read=9 -e write=9 -ot ./realtime -s/dev/ttyUSB0 shinkansen.speeds.record homes.record +# valgrind ./realtime -s/dev/ttyUSB0 shinkansen.speeds.record homes.record +# strace -e read=5 -e write=5 -ot ./realtime -s/dev/ttyUSB0 shinkansen.speeds.record homes.record