chiark / gitweb /
many bugfixes; working on resolution
authorian <ian>
Sat, 26 Apr 2008 22:59:52 +0000 (22:59 +0000)
committerian <ian>
Sat, 26 Apr 2008 22:59:52 +0000 (22:59 +0000)
hostside/README.commands
hostside/TODO
hostside/commands.c
hostside/movpos.c
hostside/resolve.c
hostside/safety.c
hostside/safety.h
hostside/trackloc.c
hostside/x.gdb

index c4e60c81a5455aa6343f0ac656277e9f072e7ea5..d26aa9782d4e952414a289633fd2ab06122088f2 100644 (file)
@@ -34,6 +34,7 @@ POSSIBLY-ASYNCHRONOUS REPORTING OF MESSAGES TO/FROM (MASTER) PIC
  U< resolving <some message about resolution algorithm>
 
  U< resolution inexplicable <segment>
+ U< resolution mispositioned <train> <crush-ending-segment> <distance>
  U< resolution movpos-change-failed <segment>/<poscombname>
  U< resolution problems <number-of-problems>
 
@@ -71,7 +72,9 @@ COMMANDS AND RESPONSES
   then one of these
  R< ack <command> ok
  R< ack <command> <errorcode>
- R< ack <command> <errorcode> : <remaining error message>...
+ R< ack <command> <errorcode> [<remaining info>] : <remaining error message>...
+ R< ack <command> <errorcode> SignallingPredictedProblem \
+          <problematic-train> <problematic-segment>|? : <error message>...
 
 ======================================================================
 
index 8e6f926ed1d6a6c40a125f57f56e3cbd9d41dc06..6f19047a9cf43ada900d9f8a263b03aca5ffa30e 100644 (file)
@@ -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 ?
index dff85353058583f4265abbd37622c3d92ae5be8f..6066bfffc32561bcfe476cd33a0053b50f1c528a 100644 (file)
@@ -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{                                  \
index e682abe5d43d6432daf09a10c129e88452b3fc27..24f9143c89dee7a4551e1ddeab2d281e6c533f62 100644 (file)
@@ -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;
index bda9b4713fe1d9726c24eaf2e9c4c45b5bd9e57c..6d9c7992b5cc22998c913e5a333e569c4b82efc5 100644 (file)
 /*
  * 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();
 }
index c9be91bbd7816937ac988c9b841f6436eab3acef..4d234870aeb67b1c3e5ebc263ec448a1d8e480be 100644 (file)
@@ -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:
index 1c4c4746b477e6ef57855a415be64837a8a955e4..eb9bec584ca07ffa11c1e4c1cad1f04dc60e7d12 100644 (file)
@@ -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 */
 
index 3305861eea4bbbc8b3f03b78e791552ccf3be788..58384b6c1ee35c3243db17e94af456e55dc515a6 100644 (file)
@@ -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;
     }
   }
index a393f9f81e1dfd95f91691901b7af87450af1652..c19641208bed1c6bcd8508229b7d6239a1dc2ab4 100644 (file)
@@ -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