9 void actual_speed(Train *tra, int step) {
11 enco_nmra_speed126(&n, tra->addr, step, tra->backwards);
12 ouprintf("train %s speed commanding %d\n", tra->pname, step);
13 retransmit_urgent_requeue(&tra->speed.rn, &n);
16 static void xmit(Train *tra) {
17 actual_speed(tra,tra->speed.step);
20 static void decel_done(TimeoutEvent *toev) {
21 Train *tra= (void*)((char*)toev - offsetof(Train, speed.decel));
25 tra->speed.speed= tra->speedcurve[tra->speed.step];
27 DPRINTF(speed,core, "decel_done %s step %d speed %f\n",
28 tra->pname, tra->speed.step, tra->speed.speed);
31 ec= predict(tra,tnow, PREDF_OLDPLAN, 0,0, 0, 0,(char*)"deceleration done");
35 static const SpeedRange *stop_info(Train *tra, double speed) {
37 for (i=0; i<tra->n_speedregimes; i++)
38 if (speed <= tra->speedregimes[i].speed + UNMARGIN_ROUNDING)
39 return &tra->speedregimes[i];
43 static double current_speed(Train *tra, const struct timeval tnow) {
45 double v1sq, v2sq, vtsq;
46 double left_to_go, ts_v2, cs;
48 DPRINTF(speed,query, "current? %s decel.running=%d speed=%f"
49 " step=%d\n", tra->pname,
50 tra->speed.decel.running, tra->speed.speed, tra->speed.step);
52 if (!tra->speed.decel.running) return tra->speed.speed;
54 left_to_go= (tra->speed.decel.abs.tv_sec - tnow.tv_sec) * 1000.0 +
55 (tra->speed.decel.abs.tv_usec - tnow.tv_usec) * 0.001;
57 if (left_to_go <= 0) {
58 DPRINTF(speed,query, "current? decel-done\n");
59 /* we don't cancel the timeout because we need the callback to lay out
60 * the train again at the lower speed */
61 return tra->speed.speed;
65 v1= tra->speedcurve[tra->speed.step];
68 ts_v2= stop_info(tra,v2)->ts;
71 vtsq= v1sq + (v2sq-v1sq) * left_to_go / ts_v2;
73 DPRINTF(speed,query, "current? decel-inprogress v2=%f v1=%f"
74 " ts_v2=%f ltg=%f returning %f\n",
75 v2,v1, ts_v2, left_to_go, cs);
79 static double stoppingdistance(Train *tra, struct timeval tnow,
80 const SpeedRange *regime, double v) {
85 xs= tra->speedregimes[tra->n_speedregimes-1].xs;
87 double v_ts_vcrit= v * regime->ts; if (xs > v_ts_vcrit) xs= v_ts_vcrit;
88 double xs_vcrit= regime->xs; if (xs > xs_vcrit) xs= xs_vcrit;
90 return xs + v * MARGIN_STOPTIME;
93 void speedmanager_getinfo(Train *tra, struct timeval tnow, SpeedInfo *ir) {
94 double vnow= current_speed(tra,tnow);
96 ir->max_speed_estimate= vnow * MARGIN_SPEED;
97 ir->stopping_distance= stoppingdistance(tra,tnow, stop_info(tra,vnow), vnow);
98 ir->stopping= !tra->speed.step;
100 DPRINTF(speed,query, "getinfo? %s max=%f stopdist=%d %c\n", tra->pname,
101 ir->max_speed_estimate, ir->stopping_distance,
105 int speedmanager_stopped(Train *tra) {
106 return tra->speed.speed == 0;
109 static ErrorCode request_core(Train *tra, int step, struct timeval tnow,
110 PredictionProblemCallback *ppc, void *ppcu) {
112 double vnow, vtarg, vmax;
114 const SpeedRange *regime;
117 DPRINTF(speed,core, "request %s%s step %d\n",
118 tra->backwards?"-":"",tra->pname,
121 if (step == tra->speed.step)
124 vnow= current_speed(tra,tnow);
125 vtarg= tra->speedcurve[step];
126 oldmaxinto= tra->maxinto;
128 DPRINTF(speed,core, " request vnow=%f vtarg=%f\n", vnow,vtarg);
130 vmax= MAX(vtarg,vnow);
131 try.max_speed_estimate= vmax * MARGIN_SPEED;
132 regime= stop_info(tra,vmax);
133 try.stopping_distance= stoppingdistance(tra,tnow, regime, vmax);
137 Segment *fdet= tra->foredetect;
138 tra->maxinto= fdet->i->poscombs[fdet->movposcomb].dist;
139 assert(tra->maxinto >= oldmaxinto);
140 tra->uncertainty += tra->maxinto - oldmaxinto;
143 ec= predict(tra,tnow,
144 step <= tra->speed.step ? PREDF_OLDPLAN : 0,
145 0,0, &try, ppc,ppcu);
147 tra->uncertainty -= tra->maxinto - oldmaxinto;
148 tra->maxinto= oldmaxinto;
149 ec2= predict(tra,tnow, PREDF_OLDPLAN,0,0, 0,
150 0,(char*)"abandoned acceleration");
155 toev_stop(&tra->speed.decel);
156 tra->speed.step= step;
157 tra->speed.speed= vmax;
160 tra->speed.decel.duration= regime->ts;
161 toev_start(&tra->speed.decel);
163 report_train_position(tra);
168 ErrorCode speedmanager_speedchange_request(Train *tra, int step,
169 PredictionProblemCallback *ppc, void *ppcu) {
173 MUSTECR( safety_checktrain(tra,ppc,ppcu) );
174 mgettimeofday(&tnow);
175 return request_core(tra,step,tnow,ppc,ppcu);
178 void speedmanager_safety_stop(Train *tra, struct timeval tnow) {
180 ec= request_core(tra,0,tnow,0,(char*)"emergency stop");
184 void speedmanager_reset_train(Train *tra) {
186 toev_init(&tra->speed.decel);
187 tra->speed.decel.callback= decel_done;
188 tra->speed.decel.pclass= "decel";
189 tra->speed.decel.pinst= tra->pname;
194 actual_speed(tra, 0);