@@ -148,7 +148,8 @@ cda_rail::simulator::GreedySimulator::simulate(
148148 for (const auto & tr : trains_in_network) {
149149 const auto & train_object = instance->get_train_list ().get_train (tr);
150150
151- if (trains_finished_simulating.contains (tr) || t < tr_stop_until.at (tr)) {
151+ if (trains_finished_simulating.contains (tr) ||
152+ t < tr_stop_until.at (tr) + dt) {
152153 PLOGV << train_object.name << " skipped." ;
153154 continue ;
154155 }
@@ -162,36 +163,54 @@ cda_rail::simulator::GreedySimulator::simulate(
162163 }
163164 assert (h % dt == 0 );
164165
165- const auto [tr_ma, tr_v1] =
166+ // const auto [tr_ma, tr_v1] =
167+ const auto tr_ma_data =
166168 get_ma_and_maxv (tr, train_velocities, tr_next_stop_id.at (tr), h, dt,
167169 train_positions, trains_in_network, trains_left,
168170 trains_on_edges, limit_speed_by_leaving_edges);
169171 PLOGV << train_object.name << " positioned at "
170172 << train_positions.at (tr).second
171- << " has MA: " << train_positions.at (tr).second + tr_ma
172- << " and max velocity: " << tr_v1;
173+ << " has MA: " << train_positions.at (tr).second + tr_ma_data.ma
174+ << " (without route end this would be: "
175+ << train_positions.at (tr).second + tr_ma_data.ma_without_route_end
176+ << " )"
177+ << " and max velocity: " << tr_ma_data.max_v
178+ << " (without route end this would be: "
179+ << tr_ma_data.max_v_without_route_end << " )" ;
173180 const auto tr_edge_len = train_edge_length (tr);
181+
182+ PLOGV << " h = " << h;
183+ auto tr_new_speed =
184+ std::min (tr_ma_data.max_v ,
185+ get_v1_from_ma (train_velocities.at (tr), tr_ma_data.ma ,
186+ train_object.deceleration , dt));
187+ if (tr_new_speed < V_MIN) {
188+ tr_new_speed = 0.0 ; // Train is stopped
189+ }
190+ auto tr_new_speed_without_route_end =
191+ std::min (tr_ma_data.max_v_without_route_end ,
192+ get_v1_from_ma (train_velocities.at (tr),
193+ tr_ma_data.ma_without_route_end ,
194+ train_object.deceleration , dt));
195+ if (tr_new_speed_without_route_end < V_MIN) {
196+ tr_new_speed_without_route_end = 0.0 ;
197+ }
198+
199+ PLOGV << " tr_new_speed = " << tr_new_speed
200+ << " (without route end this would be: "
201+ << tr_new_speed_without_route_end << " )" ;
202+
174203 if ((braking_distances.at (tr) < 0 ) &&
175- (instance->const_n ().get_edge (train_edges.at (tr).back ()).target !=
176- tr_schedule.get_exit ()) &&
177- (train_positions.at (tr).second + tr_ma + STOP_TOLERANCE >=
178- tr_edge_len)) {
204+ (tr_new_speed < tr_new_speed_without_route_end)) {
179205 PLOGV << train_object.name
180206 << " starts braking due to end of route constraint." ;
181207 braking_times.at (tr) = t - dt;
182208 braking_distances.at (tr) = tr_edge_len - train_positions.at (tr).second ;
183209 }
184- PLOGV << " h = " << h;
185- auto tr_new_speed =
186- std::min (tr_v1, get_v1_from_ma (train_velocities.at (tr), tr_ma,
187- train_object.deceleration , dt));
188- if (tr_new_speed < V_MIN) {
189- tr_new_speed = 0.0 ; // Train is stopped
190- }
191210
192211 // Move trains
193- if (move_train (tr, train_velocities.at (tr), tr_new_speed, tr_ma, dt ,
194- train_positions)) {
212+ if (move_train (tr, train_velocities.at (tr), tr_new_speed, tr_ma_data. ma ,
213+ dt, train_positions)) {
195214 movement_detected = true ;
196215 }
197216 train_velocities.at (tr) = tr_new_speed;
@@ -249,6 +268,11 @@ cda_rail::simulator::GreedySimulator::simulate(
249268 stop_times.at (tr).push_back (static_cast <double >(t));
250269 tr_next_stop_id.at (tr) = {};
251270 trains_finished_simulating.insert (tr);
271+ // set braking_times to the route end. Only after stopping at the
272+ // station, the underdefined route is the only cause for the train not
273+ // to continue
274+ braking_times.at (tr) = exit_times.at (tr);
275+ braking_distances.at (tr) = 0 ;
252276 PLOGV << " At time " << t << " , "
253277 << instance->get_train_list ().get_train (tr).name
254278 << " reached the end of its route at station "
@@ -378,8 +402,8 @@ cda_rail::simulator::GreedySimulator::simulate(
378402 })) {
379403 PLOGV << " Vertex headway constraint prevents movement." ;
380404 reason_found = true ;
381- } else if (std::ranges::any_of (tr_stop_until, [t](int stop_time) {
382- return stop_time > t;
405+ } else if (std::ranges::any_of (tr_stop_until, [t, dt ](int stop_time) {
406+ return stop_time + dt > t;
383407 })) {
384408 PLOGV << " Train stop constraint prevents movement." ;
385409 reason_found = true ;
@@ -849,7 +873,7 @@ double cda_rail::simulator::GreedySimulator::get_absolute_distance_ma(
849873 // range
850874}
851875
852- std::pair< double , double >
876+ cda_rail::simulator::GreedySimulator::MaAndMaxVResult
853877cda_rail::simulator::GreedySimulator::get_future_max_speed_constraints (
854878 size_t tr, const cda_rail::Train& train, double pos, double v_0,
855879 double max_displacement, int dt, bool also_limit_by_leaving_edges) const {
@@ -890,26 +914,6 @@ cda_rail::simulator::GreedySimulator::get_future_max_speed_constraints(
890914 double ma = max_displacement;
891915
892916 const auto milestones = edge_milestones (tr);
893-
894- // Check exit
895- const auto & last_edge_id = train_edges.at (tr).back ();
896- const auto & last_edge = instance->const_n ().get_edge (last_edge_id);
897- const auto tr_schedule = instance->get_schedule (tr);
898- const bool last_edge_leaves_network =
899- (last_edge.target == tr_schedule.get_exit ());
900- const auto relevant_last_pos =
901- milestones.back () + (last_edge_leaves_network
902- ? train.length
903- : 0 ); // + train.length because train needs to
904- // fully leave the network
905- if (pos + max_displacement >= relevant_last_pos) {
906- const double last_edge_exit_restriction =
907- last_edge_leaves_network ? tr_schedule.get_v_n () : 0 ;
908- std::tie (ma, max_v) = speed_restriction_helper (
909- ma, max_v, pos, relevant_last_pos, v_0, last_edge_exit_restriction,
910- train.deceleration , dt);
911- }
912-
913917 for (size_t i = 0 ; i < train_edges.at (tr).size () &&
914918 milestones.at (i) + EPS < pos + max_displacement;
915919 ++i) {
@@ -933,7 +937,35 @@ cda_rail::simulator::GreedySimulator::get_future_max_speed_constraints(
933937 edge.max_speed , train.deceleration , dt);
934938 }
935939 }
936- return {ma, max_v};
940+
941+ // Check exit
942+ const auto & last_edge_id = train_edges.at (tr).back ();
943+ const auto & last_edge = instance->const_n ().get_edge (last_edge_id);
944+ const auto tr_schedule = instance->get_schedule (tr);
945+ const bool last_edge_leaves_network =
946+ (last_edge.target == tr_schedule.get_exit ());
947+ const auto relevant_last_pos =
948+ milestones.back () + (last_edge_leaves_network
949+ ? train.length
950+ : 0 ); // + train.length because train needs to
951+ // fully leave the network
952+ double ma_without_route_end = ma;
953+ double max_v_without_route_end = max_v;
954+ if (pos + max_displacement >= relevant_last_pos) {
955+ const double last_edge_exit_restriction =
956+ last_edge_leaves_network ? tr_schedule.get_v_n () : 0 ;
957+ std::tie (ma, max_v) = speed_restriction_helper (
958+ ma, max_v, pos, relevant_last_pos, v_0, last_edge_exit_restriction,
959+ train.deceleration , dt);
960+ }
961+ if (last_edge_leaves_network) {
962+ ma_without_route_end = ma;
963+ max_v_without_route_end = max_v;
964+ }
965+ return {.ma = ma,
966+ .ma_without_route_end = ma_without_route_end,
967+ .max_v = max_v,
968+ .max_v_without_route_end = max_v_without_route_end};
937969}
938970
939971std::pair<double , double >
@@ -1134,7 +1166,8 @@ cda_rail::simulator::GreedySimulator::time_to_exit_objective(
11341166 static_cast <double >(dt)};
11351167}
11361168
1137- std::pair<double , double > cda_rail::simulator::GreedySimulator::get_ma_and_maxv (
1169+ cda_rail::simulator::GreedySimulator::MaAndMaxVResult
1170+ cda_rail::simulator::GreedySimulator::get_ma_and_maxv (
11381171 size_t tr, const std::vector<double >& train_velocities,
11391172 std::optional<size_t > next_stop, int h, int dt,
11401173 const std::vector<std::pair<double , double >>& train_positions,
@@ -1153,14 +1186,20 @@ std::pair<double, double> cda_rail::simulator::GreedySimulator::get_ma_and_maxv(
11531186 double max_v = NAN;
11541187 ma = get_absolute_distance_ma (tr, ma, train_positions, train_velocities,
11551188 trains_in_network, trains_left, tr_on_edges);
1156- std::tie (ma, max_v) = get_future_max_speed_constraints (
1189+ const auto tmp_ma_data = get_future_max_speed_constraints (
11571190 tr, train, train_positions.at (tr).second , train_velocities.at (tr), ma, dt,
11581191 also_limit_speed_by_leaving_edges);
1159- max_v = std::min (max_v, get_max_speed_exit_headway (
1160- tr, train, train_positions.at (tr).second ,
1161- train_velocities.at (tr), h, dt));
1162-
1163- return {ma, max_v};
1192+ ma = tmp_ma_data.ma ;
1193+ const double max_speed_exit_h = get_max_speed_exit_headway (
1194+ tr, train, train_positions.at (tr).second , train_velocities.at (tr), h, dt);
1195+ max_v = std::min (tmp_ma_data.max_v , max_speed_exit_h);
1196+ const double max_v_without_route_end =
1197+ std::min (tmp_ma_data.max_v_without_route_end , max_speed_exit_h);
1198+
1199+ return {.ma = ma,
1200+ .ma_without_route_end = tmp_ma_data.ma_without_route_end ,
1201+ .max_v = max_v,
1202+ .max_v_without_route_end = max_v_without_route_end};
11641203}
11651204
11661205double cda_rail::simulator::GreedySimulator::get_v1_from_ma (double v_0,
0 commit comments