utils.o serialio.o parseutils.o auproto-pic.o \
nmra.o encode.o movpos.o \
../layout/ours.layout-data.o \
- __oop-read-copy.o -loop
+ __oop-read-copy.o -loop -lm
$(LINK)
proto-expanded: ../cebpic/README.protocol
#endif
#endif
+
+static void cmd_ppc(Train *tra, Segment *seg, void *pu, const char *message) {
+ const CmdInfo *ci= pu;
+ oprintf(UPO,"ack SignallingPredictedProblem %s %s", ci->name, message);
+}
+
+#define MUSTECRPREDICT(requester) do{ \
+ int mustecr__ec= (requester); \
+ if (mustecr__ec==EC_SignallingPredictedProblem) return EC_BadCmd; \
+ if (mustecr__ec) return mustecr__ec; \
+ }while(0)
+#define CMDPPC cmd_ppc,(void*)ci
+
struct NmraParseEncodeCaller {
ParseState *ps;
unsigned long arg[NMRA_MAX_NARGS];
}
static int cmd_movfeat(ParseState *ps, const CmdInfo *ci) {
- Segment *move, *back, *fwd;
+ Segment *move;
const SegmentInfo *movei;
long ms;
long poscomb;
MUSTECR( ps_needsegmentperhaps(ps,&move,&movei) );
MUSTECR( ps_needword(ps) );
if (CTYPE(isdigit,*ps->thisword)) {
- back= fwd= 0;
if (!move) badcmd(ps,"invalid movement specification");
ps_pushbackword(ps);
MUSTECR( ps_neednumber(ps,&poscomb,0,movei->n_poscombs,
"position number") );
} else {
- poscomb= -1;
+ Segment *back, *fwd;
back= move;
MUSTECR( ps_needsegment(ps,&move,&movei) );
MUSTECR( ps_needsegmentperhaps(ps,&fwd,0) );
+ MUSTECR( movpos_findcomb_bysegs(back,move,fwd,move->movposcomb,&poscomb) );
}
ms= INT_MAX;
MUSTECR( ps_neednoargs(ps) );
if (!ci->xarg)
- MUSTECR( safety_check_movposchange(move) );
+ MUSTECRPREDICT( safety_check_movposchange(move,CMDPPC) );
- MUSTECR( movpos_change_bysegs(back,move,fwd,ms,0) );
+ MUSTECR( movpos_change(move,poscomb,ms,0) );
return 0;
}
static int cmd_speed(ParseState *ps, const CmdInfo *ci) {
- long speed, max;
- int curvesz;
+ long speed;
Train *tra;
MUSTECR( ps_needtrain(ps,&tra) );
- curvesz= tra->accel.curvesz;
- switch (ci->xarg) {
- case 0: max=INT_MAX; break;
- case 1: max=1000; break;
- case 2: max=126; break;
- default: abort();
- }
-
- MUSTECR( ps_neednumber(ps,&speed,0,max,"speed step") );
+ MUSTECR( ps_neednumber(ps,&speed,0,126,"speed step") );
MUSTECR( ps_neednoargs(ps) );
- switch (ci->xarg) {
- case 0:
- break;
- case 1:
- speed= speed / 1000.0 * tra->accel.curve[curvesz-1].speed;
- break;
- case 2:
- if (speed >= curvesz) speed= curvesz-1;
- speed= tra->accel.curve[speed].speed;
- break;
- }
+ MUSTECRPREDICT( speedmanager_speedchange_request(tra,speed,CMDPPC) );
- return safety_requestspeed(tra, speed);
+ return 0;
}
const CmdInfo toplevel_cmds[]= {
{ "noop", cmd_noop },
{ "movfeat", cmd_movfeat },
{ "movfeat!", cmd_movfeat, 1 },
- { "speedmms", cmd_speed, 1 },
- { "speedpermil",cmd_speed, 2 },
- { "speed126", cmd_speed, 0 },
+ { "speed", cmd_speed },
{ 0 }
};
MovFeatTooLate
MovFeatKindsCombination
MovFeatReservationInapplicable
+ MovFeatRouteNotFound
BufferFull
BadCmd
- NotFound
SignallingPredictedProblem
SignallingHorizonReached
);
/* Kind-independent code is responsible for determining
* the method, doing a bit of cleanup, and adjusting the flow
* slightly. Per-kind code does the actual work and is mostly in
- * charge - it is also responsible for updating seg->moving.
+ * charge - it is also responsible for updating seg->moving and ->motion.
*/
/* The following states exist for each MovPosChange
* at points when control flow passes between kind and indep:
* C Confirmed motion queued and will occur
* D Done motion is complete and callback just needs to be made
* E Erroneous indep must call destroy straight away
- * seg->moving is in one of the states UC
+ * seg->moving and ->motion is in one of the states UC
*/
typedef struct MovPosChange { /* valid in: filled in by and when: */
} Change;
/* `actual' contains the kind's public opinion about the physical
* state. It is initialised by indep (just before confirm) from
- * move->moving->actual or move->movposcomb as the case may be. It
+ * move->motion->actual or move->movposcomb as the case may be. It
* should be updated by the kind, since it is used by indep for
* calculating the number and identities of the features which may
* need to change when a new move request is intended to replace an
/* indep guarantees that
* alloc_motions >= move->i->n_motions on reserve
* alloc_motions >= n_motions on confirm
- * and that if on entry to reserve move->moving is non-0,
- * it is of the same kind
+ * and that if on entry to reserve move->motion is non-0,
+ * it move->motion is non-0 and of the same kind
*/
};
/* state A or R */
pt_dequeue(r);
/* states of existing: */
- PointReq *existing= (PointReq*)move->moving; /* U or C */
- if (existing) pt_dequeue(existing); /* U or CA */
+ PointReq *existing=
+ move->moving ? (PointReq*)move->motion : 0; /* U or C */
+ if (existing) pt_dequeue(existing); /* U or CA */
/* state A or RA */
memcpy(r->motions, motions, sizeof(r->motions[0])*n_motions);
*/
if (!ec) {
- move->moving= chg;
+ move->moving= 1;
+ move->motion= chg;
move->movposcomb= -1;
pt_check_action();
}
* eg if we are asked to move the
*/
Segment *move= r->h.move;
- assert(move->moving == (Change*)r);
+ assert(move->moving && move->motion == (Change*)r);
pt_queue_remove_index(&pt_confirmed,0);
pt_mark_as_allocated(r); /* now state A aka Done */
move->movposcomb= r->h.actual;
move->moving= 0;
+ move->motion= 0;
free(r);
pt_check_action();
}
for (i=0; i<pt_confirmed.n; i++) {
PointReq *r= pt_confirmed.l[i];
Segment *move= r->h.move;
- assert(move->moving == (Change*)r);
+ assert(move->motion == (Change*)r);
move->moving= 0;
+ move->motion= 0;
move->movposcomb= r->h.actual;
free(r);
}
if (startpoint<0) startpoint= movpos_poscomb_actual(move);
- for (feat=0, feati=movei->movfeats, tchanges=0, kind= mfk_none;;
+ for (feat=0, feati=movei->movfeats, tchanges=0, kind= mfk_none;
feat<movei->n_movfeats;
feat++, feati++) {
if (!change_needed(feati,target,startpoint)) continue;
for (tcomb=0, pci=movei->poscombs;
tcomb<movei->n_poscombs;
tcomb++, pci++) {
- Segment *tback= &segments[pci->backwards.next];
- Segment *tfwd= &segments[pci->forwards .next];
+ Segment *tback= &segments[pci->link[1].next];
+ Segment *tfwd= &segments[pci->link[0].next];
if (back && !(back==tback || back==tfwd)) continue;
if (fwd && !(fwd ==tback || fwd ==tfwd)) continue;
}
if (*chosen_r) *chosen_r= bestcomb;
return
- tchanges==INT_MAX ? EC_Invalid :
- tchanges==INT_MAX-1 ? EC_MovFeatKindsCombination :
+ bestchanges==INT_MAX ? EC_MovFeatRouteNotFound :
+ bestchanges==INT_MAX-1 ? EC_MovFeatKindsCombination :
0;
}
if (chg) {
if (chg->ki != ki ||
chg->move != move ||
- chg->intent != intent)
+ chg->intent != target)
return EC_MovFeatReservationInapplicable;
} else {
chg= mp_allocate(ki,move,n_motions,target);
movpos_reserve(Segment *move, int maxdelay_ms, MovPosChange **res_r,
MovPosComb target, MovPosComb startpoint /*as for findcomb*/) {
MovFeatKind kind= mfk_none;
- const MovFeatInfo *feati;
ErrorCode ec;
- int feat, nchanges;
+ int nchanges;
nchanges= evaluate_target(move,target,startpoint,&kind);
- if (nchanges=-1) return EC_MovFeatKindsCombination;
+ if (nchanges==-1) return EC_MovFeatKindsCombination;
const KindInfo *ki= &methodinfos[kind];
Change *chg= mp_allocate(ki, move, move->i->n_movfeats, target);
}
MovPosComb movpos_poscomb_actual(Segment *seg) {
- return seg->moving ? seg->moving->actual : seg->movposcomb;
+ return seg->moving ? seg->motion->actual : seg->movposcomb;
}
MovPosComb movpos_change_intent(MovPosChange *chg) {
mapmem(0, datalen, PROT_READ);
}
+#define SANE_SEGMENT(seg)
+
void persist_entrails_run_converter(void) {
- TRA_IV;
SEG_IV;
MovPosComb report;
persist_mapread();
- FOR_TRA {
- if (!tra->pname || !tra->foredetect ||
- !tra->foredetect->i || !tra->foredetect->i->pname)
- continue;
- printf("train %s at %s%s:%d-+%d\n",
- tra->pname, tra->backwards ? "-" : "",
-fixme tra->backwards is wrong
- need to provide both tra->backwards and tr_backwards
- tra->foredetect->i->pname, tra->mininto, tra->uncertainty);
- }
FOR_SEG {
if (seg->i != segi || !segi->pname ||
!seg->owner || !seg->owner->pname)
continue;
- printf("seg %s has %s%s\n",
- segi->pname, seg->tr_backwards ? "-" : "", seg->owner->pname);
+ printf("seg %s has %s%s\n", segi->pname,
+ (seg->tr_backwards & seg->owner->backwards) ? "-" : "",
+ seg->owner->pname);
if (segi->n_poscombs>1 &&
(report= movpos_poscomb_actual(seg)) >=0 &&
#include "record.h"
#include "record-y.h"
-void record_train_at(Train *tra, int backw, Segment *seg);
void record_train_is(Train *tra, int addr, int head, int det, int tail);
+void record_train_home(Train *tra, int backw, Segment *seg);
void record_train_step_speed(Train *tra, int step, double speed);
void record_train_stopregime_count(void);
void record_train_stopregime(Train *tra, double speed, int xs, int ts);
-void record_train_home(Train *tra, int backw, Segment *seg);
void record_seg_has(Segment *seg, int backw, Train *tra);
void record_seg_at(Segment *seg, const char *movposcomb_pname);
void record_feature_nmrafeat(FeaturesFeature*, FeaturesAddr*, int num);
| TRAIN train IS NUM NUM '+' NUM '+' NUM
{ if ($2) record_train_is($2,$4,$5,$7,$9);
}
- | TRAIN train AT backwards seg ':' NUM '+' '-' NUM
- { if ($2) record_train_at($2,$4,$5,$7,$10);
- }
- | TRAIN train AT backwards seg ':' NUM '+' '-' NUM
- { if ($2) record_train_at($2,$4,$5,$7,$10);
- }
| TRAIN train HOME { cur_train=$2; } segments
{
}
tra->tail= tail;
}
-void record_train_at(Train *tra, int backw, Segment *seg, int mini, int unc) {
- tra->foredetect= seg;
- tra->maxinto= maxi;
- tra->uncertainty= unc;
- tra->backwards= backw;
-}
-
void record_train_home(Train *tra, int backw, Segment *seg) {
if (!tra) return;
seg->home= tra;
void record_train_stopregime(Train *tra, double from, int xs, int ts) {
Train *other;
- SpeedRangeEntry *new;
+ SpeedRange *new;
int i;
if (rangebufused >= rangebufsz)
static int speedregime_compare(const void *av, const void *bv) {
const SpeedRange *a= av, *b= bv;
- if (a->step == b->step)
- record_yyerror("multiple speed curve points at same step");
- return a->step - b->step;
+ if (a->speed == b->speed)
+ record_yyerror("multiple identical speed regimes");
+ return a->speed > b->speed ? 1 : -1;
}
static void speeds_postprocess(void) {
TRA_IV;
+ int step;
FOR_TRA {
if (!tra->speedregimes || tra->speedcurve[1]<0) {
SEG_IV;
void *mapbase=0;
char **trap;
- int phase, offset, datalen=0;
+ int phase, offset, datalen=0, step;
#define ALLOC(array,count) \
((array)= alloc_some(mapbase,&offset,sizeof(*(array)),(count)))
datalen= offset;
}
- curvebuf= mmalloc(sizeof(*curvebuf) * curvebufsz);
+ rangebuf= mmalloc(sizeof(*rangebuf) * rangebufsz);
}
/*---------- entrypoint from main, and its subroutines ----------*/
}
void records_parse(const char **argv) {
- parse_pass(argv); /* trains==0: counts trains and curve points. */
+ parse_pass(argv); /* trains==0: counts trains and speed ranges. */
alloc();
parse_pass(argv); /* trains!=0: populates data area */
record_tempzone_clear();
target= d->movposcomb;
}
- if (d->owner)
- d->until_here= 1e-3;
-
if (d->i->n_poscombs>1) {
d->movposcomb= -1;
if (target >= 0) {
}
}
- FOR_TRAIN(t,NOOP,NOOP) {
- t->speed= 0;
- if (t->resolution == RR_E)
- t->backwards= 0;
- }
-
if (problems) {
x_problems:
oprintf(UPO,"resolution problems %d\n",problems);
static int findhead_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
MovPosComb *mpc_io, Segment *before) {
FindEndUserContext *u= c->u;
- if (t->seg->owner != train) return -1;
+ if (t->seg->owner != u->train) return -1;
if (!t->seg->res_detect) { u->extraspace= 0; return -1; }
- u->train->foredetect= seg;
+ u->train->foredetect= t->seg;
t->seg->tr_backwards= t->backwards;
t->seg->res_detect= 0;
return 0;
static int walkback_nextseg(TrackLocation *t, struct TrackAdvanceContext *c,
MovPosComb *mpc_io, Segment *before) {
- if (t->seg->owner != train) return -1;
+ FindEndUserContext *u= c->u;
+ if (t->seg->owner != u->train) return -1;
t->seg->tr_backwards= !t->backwards;
t->seg->resfin_done= 1;
+ return 0;
}
static void resolve_train_finalise(Segment *startpoint) {
+ SEG_IV;
Train *tra;
TrackLocation t;
TrackAdvanceContext tc;
FindEndUserContext u;
+ int r;
assert(startpoint->owner);
tra= startpoint->owner;
u.extraspace= MARGIN_NOSE + tra->head;
- r= findhead_nextseg(&t,&c,0,0); assert(!r);
+ r= findhead_nextseg(&t,&tc,0,0); assert(!r);
trackloc_advance(&t,&tc);
- tra->foredetect= u->foredetect;
- tra->maxinto= segdist(tra->foredetect) - u->extraspace;
+ tra->maxinto= segdist(tra->foredetect) - u.extraspace;
if (tra->maxinto < 0) tra->maxinto= 0;
tra->uncertainty= tra->maxinto;
r= walkback_nextseg(&t,&tc,0,0); assert(!r);
trackloc_advance(&t,&tc);
- if (u->distance) {
- tra->uncertainty -= u->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);
int noninv_tally[2];
} PredictUserContext;
+static int nose_length(Train *tra) {
+ return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head);
+}
+
/*---------- prediction problem reporting ----------*/
static ErrorCode predict_vproblem(PredictUserContext *u, Segment *seg,
/* Is it empty ? */
- if (speedmanager_stopping(train) && t->seg->owner != u->train)
+ if (speedmanager_stopping(u->train) && t->seg->owner != u->train)
return EC_SignallingHorizonReached;
if (t->seg->owner) {
u->nosec.distance= advanced;
r= trackloc_advance(&u->nose,&u->nosec);
- if (r == SignallingHorizonReached &&
+ if (r == EC_SignallingHorizonReached &&
u->was_distance==INT_MAX) {
/* Our very first `next segment' lookahead found the end. So we
* know that our nose hasn't left this segment because that's what
int adjust= nose_length(u->train);
if (adjust > u->train->maxinto) adjust= u->train->maxinto;
u->train->maxinto -= adjust;
- u->train->uncertainto += adjust;
+ u->train->uncertainty += adjust;
}
if (r) return r;
/*---------- prediction entrypoint ----------*/
-static int nose_length(Train *tra) {
- return MARGIN_NOSE + (tra->backwards ? tra->tail : tra->head);
-}
-
ErrorCode predict_confirm(Train *tra, int accelerate,
PredictionProblemCallback *ppc, void *ppcu) {
PredictUserContext u;
void safety_notify_detection(Segment *seg) {
Train *tra;
- TrackLoc tloc;
ErrorCode ec;
if (seg->det_ignore) return;
if (!seg->det_expected)
safety_panic(0,seg, "unexpected detection");
+
+ tra= seg->owner;
if (seg->movposcomb < 0)
safety_panic(tra,seg, "track route not set and train has arrived");
- tra= seg->owner;
tra->foredetect= seg;
tra->uncertainty= tra->maxinto=
seg->i->poscombs[seg->movposcomb].dist;
assert(!ec);
}
-ErrorCode safety_check_movposchange(Segment *seg) {
+ErrorCode safety_check_movposchange(Segment *seg,
+ PredictionProblemCallback *ppc, void *ppcu) {
+ PredictUserContext u;
+
+ u.problem_callback= ppc;
+ u.problem_callback_u= ppcu;
+ u.train= seg->owner;
+
if (seg->owner) {
- oprintf(UPO,"ack SignallingProblemPredicted @%s %s:"
- " route set for approaching train",
- seg->i->pname, seg->owner->pname);
- return EC_BadCmd;
+ return predict_problem(&u,seg, " route set for approaching train");
}
return 0;
}
void safety_notify_detection(Segment *seg);
/* Called by startup.c when new train detection occurs in state Run. */
-ErrorCode safety_check_movposchange(Segment *seg);
+ErrorCode safety_check_movposchange(Segment *seg,
+ PredictionProblemCallback *ppc, void *ppcu);
/* If this check success, caller may call movpos_change */
ErrorCode predict_confirm(Train *tra, int accelerate,
void speedmanager_reset_train(Train *tra);
double speedmanager_speed_maxestimate(Train *tra);
double speedmanager_stoppingdistance(Train *tra);
-int speedmanager_speed_stopping(Train *tra);
+int speedmanager_stopping(Train *tra);
/*========== actual.c ==========*/
/* actual.c should only be called from safety.c.
* traversed. */
int trackloc_reverse_exact(TrackLocation *t, TrackAdvanceContext *c);
+int trackloc_set_exactinto(TrackLocation *t, TrackAdvanceContext *c,
+ Segment *seg, int backwards, int into);
/* c is used just as for trackloc_getlink.
* If we can't determine the movposcombs we call abort. */
return xs;
}
-int speedmanager_speed_stopping(Train *tra) {
+int speedmanager_stopping(Train *tra) {
return tra->speed.try_speed < 0 && !tra->speed.speed;
}
tloc->remain= 0;
}
+int trackloc_set_exactinto(TrackLocation *t, TrackAdvanceContext *c,
+ Segment *seg, int backwards, int into) {
+ const SegPosCombInfo *pci;
+ int r;
+
+ r= trackloc_getlink(t,c,&pci,0,-1);
+ if (r) return r;
+ assert(pci);
+
+ t->seg= seg;
+ t->backwards= backwards;
+ t->remain= pci->dist - into;
+ return 0;
+}
+
/*---------- enquirers ----------*/
int trackloc_getlink(TrackLocation *t, TrackAdvanceContext *c,
const SegPosCombInfo *pci;
const SegmentLinkInfo *link;
MovPosComb mpc_nego;
- int leaving_back;
int r;
r= trackloc_getlink(t,c, 0,&link, t->seg->movposcomb);