Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSRailSignal.cpp
15 : /// @author Melanie Weber
16 : /// @author Andreas Kendziorra
17 : /// @author Jakob Erdmann
18 : /// @date Jan 2015
19 : ///
20 : // A rail signal logic
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <cassert>
25 : #include <utility>
26 : #include <vector>
27 : #include <bitset>
28 : #ifdef HAVE_FOX
29 : #include <utils/foxtools/MFXWorkerThread.h>
30 : #endif
31 : #include <utils/iodevices/OutputDevice_COUT.h>
32 : #include <microsim/MSEventControl.h>
33 : #include <microsim/MSNet.h>
34 : #include <microsim/MSEdge.h>
35 : #include <microsim/MSEdgeControl.h>
36 : #include <microsim/MSLane.h>
37 : #include <microsim/MSLink.h>
38 : #include <microsim/MSVehicle.h>
39 : #include <microsim/devices/MSDevice_Routing.h>
40 : #include <microsim/devices/MSRoutingEngine.h>
41 : #include <microsim/MSLane.h>
42 :
43 : #include "MSTLLogicControl.h"
44 : #include "MSTrafficLightLogic.h"
45 : #include "MSPhaseDefinition.h"
46 : #include "MSTLLogicControl.h"
47 : #include "MSRailSignalConstraint.h"
48 : #include "MSRailSignalControl.h"
49 : #include "MSDriveWay.h"
50 : #include "MSRailSignal.h"
51 :
52 : //#define DEBUG_SELECT_DRIVEWAY
53 : //#define DEBUG_DRIVEWAY_UPDATE
54 : //#define DEBUG_SIGNALSTATE
55 : //#define DEBUG_REROUTE
56 :
57 : #define DEBUG_COND DEBUG_HELPER(this)
58 : #define DEBUG_COND_LINKINFO DEBUG_HELPER(myLink->getTLLogic())
59 : #define DEBUG_HELPER(obj) ((obj)->isSelected())
60 : //#define DEBUG_HELPER(obj) ((obj)->getID() == "")
61 : //#define DEBUG_HELPER(obj) (true)
62 :
63 : // ===========================================================================
64 : // static value definitions
65 : // ===========================================================================
66 :
67 : bool MSRailSignal::myStoreVehicles(false);
68 : MSRailSignal::VehicleVector MSRailSignal::myBlockingVehicles;
69 : MSRailSignal::VehicleVector MSRailSignal::myRivalVehicles;
70 : MSRailSignal::VehicleVector MSRailSignal::myPriorityVehicles;
71 : std::string MSRailSignal::myConstraintInfo;
72 : int MSRailSignal::myRSIndex(0);
73 : std::vector<const MSDriveWay*> MSRailSignal::myBlockingDriveWays;
74 : std::string MSRailSignal::myRequestedDriveWay;
75 :
76 : // ===========================================================================
77 : // method definitions
78 : // ===========================================================================
79 5065 : MSRailSignal::MSRailSignal(MSTLLogicControl& tlcontrol,
80 : const std::string& id, const std::string& programID, SUMOTime delay,
81 5065 : const Parameterised::Map& parameters) :
82 : MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
83 5065 : myNumericalID(myRSIndex++),
84 15195 : myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
85 5065 : myPhaseIndex(0),
86 5065 : myDriveWayIndex(0) {
87 5065 : myDefaultCycleTime = DELTA_T;
88 5065 : myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
89 5065 : mySwitchCommand->deschedule(this);
90 5065 : }
91 :
92 : void
93 5065 : MSRailSignal::init(NLDetectorBuilder&) {
94 5065 : if (myLanes.size() == 0) {
95 9 : WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
96 : }
97 : SVCPermissions outgoingPermissions = 0;
98 11461 : for (LinkVector& links : myLinks) { //for every link index
99 6396 : if (links.size() != 1) {
100 0 : throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
101 0 : + " links controlled by index " + toString(links[0]->getTLIndex()));
102 : }
103 12792 : myLinkInfos.push_back(LinkInfo(links[0]));
104 6396 : outgoingPermissions |= links[0]->getPermissions();
105 : }
106 5065 : updateCurrentPhase();
107 5065 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
108 5065 : myNumLinks = (int)myLinks.size();
109 5065 : MSRailSignalControl::getInstance().addSignal(this);
110 5065 : myMovingBlock |= MSRailSignalControl::isMovingBlock(outgoingPermissions);
111 5065 : }
112 :
113 :
114 10130 : MSRailSignal::~MSRailSignal() {
115 5065 : removeConstraints();
116 10130 : }
117 :
118 :
119 : // ----------- Handling of controlled links
120 : void
121 0 : MSRailSignal::adaptLinkInformationFrom(const MSTrafficLightLogic& logic) {
122 0 : MSTrafficLightLogic::adaptLinkInformationFrom(logic);
123 0 : updateCurrentPhase();
124 0 : }
125 :
126 :
127 : // ------------ Switching and setting current rows
128 : SUMOTime
129 0 : MSRailSignal::trySwitch() {
130 : // deschedule regular traffic light event,
131 : // updateCurrentPhase is instead called from MSRailSignalControl::updateSignals
132 0 : return SUMOTime_MAX;
133 : }
134 :
135 :
136 :
137 : bool
138 17631820 : MSRailSignal::updateCurrentPhase() {
139 : #ifdef DEBUG_SIGNALSTATE
140 : gDebugFlag4 = DEBUG_COND;
141 : #endif
142 : bool keepActive = false;
143 : // green by default so vehicles can be inserted at the borders of the network
144 : std::string state(myLinks.size(), 'G');
145 51835898 : for (LinkInfo& li : myLinkInfos) {
146 34204078 : if (li.myLink->getApproaching().size() > 0 && li.myControlled) {
147 : keepActive = true;
148 8856208 : Approaching closest = li.myLink->getClosest();
149 8856208 : MSDriveWay& driveway = li.getDriveWay(closest.first);
150 : //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
151 : //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
152 8856208 : const bool mustWait = !constraintsAllow(closest.first, true);
153 : MSEdgeVector occupied;
154 8856208 : if (mustWait || !driveway.reserve(closest, occupied)) {
155 8478243 : state[li.myLink->getTLIndex()] = 'r';
156 8478243 : if (occupied.size() > 0) {
157 208265 : li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
158 : }
159 : #ifdef DEBUG_SIGNALSTATE
160 : if (gDebugFlag4) {
161 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
162 : }
163 : #endif
164 : } else {
165 377965 : state[li.myLink->getTLIndex()] = 'G';
166 : #ifdef DEBUG_SIGNALSTATE
167 : if (gDebugFlag4) {
168 : std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
169 : }
170 : #endif
171 : }
172 34204078 : } else if (li.myControlled) {
173 25347854 : if (li.myDriveways.empty()) {
174 : #ifdef DEBUG_SIGNALSTATE
175 : if (gDebugFlag4) {
176 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for unitialized signal (no driveways yet)\n";
177 : }
178 : #endif
179 16528004 : state[li.myLink->getTLIndex()] = 'r';
180 : } else {
181 8819850 : const MSDriveWay& driveway = *li.myDriveways.front();
182 : MSEdgeVector occupied;
183 8819850 : if (driveway.foeDriveWayOccupied(true, nullptr, occupied) || driveway.foeDriveWayApproached()) {
184 : keepActive = true;
185 : #ifdef DEBUG_SIGNALSTATE
186 : if (gDebugFlag4) {
187 : std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway " << driveway.getID() << "\n";
188 : }
189 : #endif
190 8777743 : state[li.myLink->getTLIndex()] = 'r';
191 : } else {
192 : #ifdef DEBUG_SIGNALSTATE
193 : if (gDebugFlag4) {
194 : std::cout << SIMTIME << " rsl=" << li.getID() << " green for default driveway " << driveway.getID() << "\n";
195 : }
196 : #endif
197 : }
198 8819850 : }
199 : } else {
200 16 : state[li.myLink->getTLIndex()] = 'O';
201 : }
202 : }
203 17631820 : if (myCurrentPhase.getState() != state) {
204 : myCurrentPhase.setState(state);
205 27301 : myPhaseIndex = 1 - myPhaseIndex;
206 : // set link priorities
207 27301 : setTrafficLightSignals(SIMSTEP);
208 : // execute switch actions (3D-gui)
209 : //const MSTLLogicControl::TLSLogicVariants& vars = myTLControl.get(myTLLogic->getID());
210 : //vars.executeOnSwitchActions();
211 : }
212 : #ifdef DEBUG_SIGNALSTATE
213 : gDebugFlag4 = false;
214 : #endif
215 17631820 : return keepActive;
216 : }
217 :
218 :
219 : bool
220 8883026 : MSRailSignal::constraintsAllow(const SUMOVehicle* veh, bool storeWaitRelation) const {
221 8883026 : if (myConstraints.size() == 0) {
222 : return true;
223 : } else {
224 16597804 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
225 : auto it = myConstraints.find(tripID);
226 8298902 : if (it != myConstraints.end()) {
227 8315346 : for (MSRailSignalConstraint* c : it->second) {
228 : // ignore insertion constraints here
229 8293469 : if (!c->isInsertionConstraint() && !c->cleared()) {
230 : #ifdef DEBUG_SIGNALSTATE
231 : if (gDebugFlag4) {
232 : std::cout << " constraint '" << c->getDescription() << "' not cleared\n";
233 : }
234 : #endif
235 8263545 : if (storeWaitRelation && MSGlobals::gTimeToTeleportRSDeadlock > 0
236 8289218 : && veh->getWaitingTime() > veh->getVehicleType().getCarFollowModel().getStartupDelay()) {
237 13926 : const SUMOVehicle* foe = c->getFoe();
238 13926 : if (foe != nullptr) {
239 11886 : MSRailSignalControl::getInstance().addWaitRelation(veh, this, foe, c);
240 : }
241 : }
242 8271904 : if (myStoreVehicles) {
243 0 : myConstraintInfo = c->getDescription();
244 : }
245 : return false;
246 : }
247 : }
248 : }
249 26998 : return true;
250 : }
251 : }
252 :
253 :
254 : void
255 935 : MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
256 935 : myConstraints[tripId].push_back(constraint);
257 935 : }
258 :
259 :
260 : bool
261 216 : MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
262 : if (myConstraints.count(tripId) != 0) {
263 216 : auto& constraints = myConstraints[tripId];
264 216 : auto it = std::find(constraints.begin(), constraints.end(), constraint);
265 216 : if (it != constraints.end()) {
266 216 : delete *it;
267 : constraints.erase(it);
268 : return true;
269 : }
270 : }
271 : return false;
272 : }
273 :
274 : void
275 5089 : MSRailSignal::removeConstraints() {
276 5879 : for (auto item : myConstraints) {
277 1509 : for (MSRailSignalConstraint* c : item.second) {
278 719 : delete c;
279 : }
280 : }
281 : myConstraints.clear();
282 5089 : }
283 :
284 :
285 : // ------------ Static Information Retrieval
286 : int
287 0 : MSRailSignal::getPhaseNumber() const {
288 0 : return 0;
289 : }
290 :
291 : const MSTrafficLightLogic::Phases&
292 5065 : MSRailSignal::getPhases() const {
293 5065 : return myPhases;
294 : }
295 :
296 : const MSPhaseDefinition&
297 0 : MSRailSignal::getPhase(int) const {
298 0 : return myCurrentPhase;
299 : }
300 :
301 : // ------------ Dynamic Information Retrieval
302 : int
303 29144 : MSRailSignal::getCurrentPhaseIndex() const {
304 29144 : return myPhaseIndex;
305 : }
306 :
307 : const MSPhaseDefinition&
308 17736168 : MSRailSignal::getCurrentPhaseDef() const {
309 17736168 : return myCurrentPhase;
310 : }
311 :
312 :
313 : void
314 1 : MSRailSignal::resetLastSwitch(SUMOTime t) {
315 1 : myCurrentPhase.myLastSwitch = t;
316 1 : }
317 :
318 :
319 : // ------------ Conversion between time and phase
320 : SUMOTime
321 0 : MSRailSignal::getPhaseIndexAtTime(SUMOTime) const {
322 0 : return 0;
323 : }
324 :
325 : SUMOTime
326 0 : MSRailSignal::getOffsetFromIndex(int) const {
327 0 : return 0;
328 : }
329 :
330 : int
331 0 : MSRailSignal::getIndexFromOffset(SUMOTime) const {
332 0 : return 0;
333 : }
334 :
335 :
336 : void
337 6396 : MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
338 6396 : if (pos >= 0) {
339 6396 : MSTrafficLightLogic::addLink(link, lane, pos);
340 : } // ignore uncontrolled link
341 6396 : }
342 :
343 :
344 : std::string
345 0 : MSRailSignal::describeLinks(std::vector<MSLink*> links) {
346 : std::string result;
347 0 : for (MSLink* link : links) {
348 0 : result += link->getDescription() + " ";
349 : }
350 0 : return result;
351 : }
352 :
353 :
354 : void
355 4381 : MSRailSignal::writeBlocks(OutputDevice& od, bool writeVehicles) const {
356 8762 : od.openTag("railSignal");
357 4381 : od.writeAttr(SUMO_ATTR_ID, getID());
358 9418 : for (const LinkInfo& li : myLinkInfos) {
359 5037 : MSLink* link = li.myLink;
360 10074 : od.openTag("link");
361 5037 : od.writeAttr(SUMO_ATTR_TLLINKINDEX, link->getTLIndex());
362 5037 : od.writeAttr(SUMO_ATTR_FROM, link->getLaneBefore()->getID());
363 5037 : od.writeAttr(SUMO_ATTR_TO, link->getViaLaneOrLane()->getID());
364 10003 : for (const MSDriveWay* dw : li.myDriveways) {
365 4966 : if (writeVehicles) {
366 458 : dw->writeBlockVehicles(od);
367 : } else {
368 4508 : dw->writeBlocks(od);
369 : }
370 : }
371 10074 : od.closeTag(); // link
372 : }
373 4381 : od.closeTag(); // railSignal
374 4381 : }
375 :
376 :
377 : void
378 3882 : MSRailSignal::initDriveWays(const SUMOVehicle* ego, bool update) {
379 3882 : const ConstMSEdgeVector& edges = ego->getRoute().getEdges();
380 3882 : int endIndex = ego->getParameter().arrivalEdge;
381 3882 : if (endIndex < 0) {
382 3879 : endIndex = (int)edges.size() - 1;
383 : }
384 3882 : int departIndex = ego->getParameter().departEdge;
385 : MSDriveWay* prev = nullptr;
386 3882 : if (update && ego->hasDeparted()) {
387 : // find last rail signal on the route and obtain the driveway
388 783 : const MSEdge* next = ego->getEdge();
389 941 : for (int i = ego->getRoutePosition() - 1; i > departIndex; i--) {
390 742 : const MSEdge* e = ego->getRoute().getEdges()[i];
391 742 : if (e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
392 586 : const MSLink* link = e->getLanes().front()->getLinkTo(next->getLanes().front());
393 : //std::cout << SIMTIME << " veh=" << ego->getID() << " rp=" << ego->getRoutePosition()
394 : // << " i=" << i << " e=" << e->getID() << " next=" << next->getID() << " link=" << (link == nullptr ? "NUL" : link->getDescription()) << "\n";
395 586 : if (link != nullptr && link->isTLSControlled()) {
396 584 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
397 584 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
398 584 : prev = &li.getDriveWay(ego, i);
399 584 : departIndex = ego->getRoutePosition();
400 584 : break;
401 : }
402 : }
403 : next = e;
404 : }
405 : }
406 783 : if (prev == nullptr) {
407 3298 : prev = const_cast<MSDriveWay*>(MSDriveWay::getDepartureDriveway(ego, true));
408 : }
409 3882 : if (update && ego->hasDeparted()) {
410 783 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
411 783 : if (!prev->hasTrain(veh) && prev->notifyEnter(*veh, prev->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(prev)) {
412 671 : veh->addReminder(prev, 1);
413 : }
414 : }
415 60047 : for (int i = departIndex; i <= endIndex - 1; i++) {
416 56165 : const MSEdge* e = edges[i];
417 56165 : if (e->isNormal() && e->getToJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
418 36471 : const MSEdge* e2 = edges[i + 1];
419 72942 : for (MSLane* lane : e->getLanes()) {
420 73888 : for (MSLink* link : lane->getLinkCont()) {
421 37417 : if (&link->getLane()->getEdge() == e2) {
422 36420 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(link->getTLLogic()));
423 33766 : if (rs != nullptr) {
424 33766 : LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
425 : // init driveway
426 33766 : MSDriveWay* dw = &li.getDriveWay(ego, i);
427 33766 : MSRailSignalControl::getInstance().addDrivewayFollower(prev, dw);
428 33766 : MSRailSignalControl::getInstance().addDWDeadlockChecks(rs, prev);
429 33766 : MSRailSignalControl::getInstance().notifyApproach(link);
430 : prev = dw;
431 33766 : if (update && rs->isActive()) {
432 : // vehicle may have rerouted its intial trip
433 : // after the states have been set
434 : // @note: This is a hack because it could lead to invalid tls-output
435 : // (it's still an improvement over switching based on default driveways)
436 31022 : if (!ego->hasDeparted()) {
437 8481 : rs->updateCurrentPhase();
438 8481 : rs->setTrafficLightSignals(SIMSTEP);
439 22541 : } else if (ego->hasDeparted() && i <= ego->getRoutePosition()) {
440 723 : MSBaseVehicle* veh = dynamic_cast<MSBaseVehicle*>(const_cast<SUMOVehicle*>(ego));
441 723 : if (!dw->hasTrain(veh) && dw->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(dw)) {
442 59 : veh->addReminder(dw, 1);
443 75 : for (MSDriveWay* sub : dw->getSubDriveWays()) {
444 16 : if (!sub->hasTrain(veh) && sub->notifyEnter(*veh, dw->NOTIFICATION_REROUTE, nullptr) && !veh->hasReminder(sub)) {
445 0 : veh->addReminder(sub, 1);
446 : }
447 : }
448 : }
449 : }
450 : }
451 : }
452 : }
453 : }
454 : }
455 : }
456 : }
457 3882 : }
458 :
459 :
460 : bool
461 17061 : MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
462 17061 : if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
463 5259 : const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
464 5052 : if (rs != nullptr && rs->myConstraints.size() > 0) {
465 6920 : const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
466 : auto it = rs->myConstraints.find(tripID);
467 3460 : if (it != rs->myConstraints.end()) {
468 3681 : for (MSRailSignalConstraint* c : it->second) {
469 3379 : if (c->isInsertionConstraint() && !c->cleared()) {
470 : #ifdef DEBUG_SIGNALSTATE
471 : if (DEBUG_HELPER(rs)) {
472 : std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
473 : }
474 : #endif
475 6216 : info = c->getDescription();
476 3108 : isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
477 3108 : if (MSGlobals::gTimeToTeleportRSDeadlock > 0) {
478 3108 : const SUMOVehicle* foe = c->getFoe();
479 3108 : if (foe != nullptr) {
480 3108 : MSRailSignalControl::getInstance().addWaitRelation(veh, rs, foe, c);
481 : }
482 : }
483 : return true;
484 : }
485 : }
486 : }
487 : }
488 : }
489 : return false;
490 : }
491 :
492 : // ===========================================================================
493 : // LinkInfo method definitions
494 : // ===========================================================================
495 :
496 6396 : MSRailSignal::LinkInfo::LinkInfo(MSLink* link):
497 6396 : myLink(link) {
498 6396 : reset();
499 6396 : }
500 :
501 14399 : MSRailSignal::LinkInfo::~LinkInfo() {
502 19823 : for (MSDriveWay* dw : myDriveways) {
503 5424 : delete dw;
504 : }
505 : myDriveways.clear();
506 14399 : }
507 :
508 : void
509 6401 : MSRailSignal::LinkInfo::reset() {
510 6401 : myLastRerouteTime = -1;
511 6401 : myLastRerouteVehicle = nullptr;
512 : myDriveways.clear();
513 6401 : myControlled = (myLink->getViaLaneOrLane()->getPermissions() & myLink->getLane()->getPermissions() & SVC_RAIL_CLASSES) != 0;
514 6401 : }
515 :
516 :
517 : std::string
518 6 : MSRailSignal::LinkInfo::getID() const {
519 12 : return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
520 : }
521 :
522 :
523 : MSDriveWay&
524 8939755 : MSRailSignal::LinkInfo::getDriveWay(const SUMOVehicle* veh, int searchStart) {
525 8939755 : MSEdge* first = &myLink->getLane()->getEdge();
526 8939755 : auto searchStartIt = searchStart < 0 ? veh->getCurrentRouteEdge() : veh->getRoute().begin() + searchStart;
527 8939755 : MSRouteIterator firstIt = std::find(searchStartIt, veh->getRoute().end(), first);
528 8939755 : if (firstIt == veh->getRoute().end()) {
529 : // possibly the vehicle has already gone past the first edge (i.e.
530 : // because first is short or the step-length is high)
531 : // lets look backward along the route
532 : // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
533 79 : double lookBack = SPEED2DIST(veh->getSpeed() + 10);
534 79 : int routeIndex = veh->getRoutePosition() - 1;
535 85 : while (lookBack > 0 && routeIndex > 0) {
536 85 : const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
537 85 : if (prevEdge == first) {
538 79 : firstIt = veh->getRoute().begin() + routeIndex;
539 79 : break;
540 : }
541 6 : lookBack -= prevEdge->getLength();
542 6 : routeIndex--;
543 : }
544 : }
545 8939755 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
546 8939755 : if (firstIt == veh->getRoute().end()) {
547 0 : WRITE_WARNING("Invalid approach information to rail signal '" + MSDriveWay::getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
548 : + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
549 0 : if (myDriveways.empty()) {
550 : ConstMSEdgeVector dummyRoute;
551 0 : dummyRoute.push_back(&myLink->getLane()->getEdge());
552 0 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, dummyRoute.begin(), dummyRoute.end());
553 0 : myDriveways.push_back(dw);
554 0 : }
555 0 : return *myDriveways.front();
556 : }
557 : //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
558 8939755 : return getDriveWay(firstIt, veh->getRoute().end(), veh->getID());
559 : }
560 :
561 :
562 : MSDriveWay&
563 8939755 : MSRailSignal::LinkInfo::getDriveWay(MSRouteIterator firstIt, MSRouteIterator endIt, const std::string& info) {
564 9153772 : for (MSDriveWay* dw : myDriveways) {
565 9148348 : if (dw->match(firstIt, endIt)) {
566 : return *dw;
567 : }
568 : #ifdef DEBUG_SELECT_DRIVEWAY
569 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " other dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
570 : #else
571 : UNUSED_PARAMETER(info);
572 : #endif
573 : }
574 5424 : MSRailSignal* rs = const_cast<MSRailSignal*>(dynamic_cast<const MSRailSignal*>(myLink->getTLLogic()));
575 5424 : MSDriveWay* dw = MSDriveWay::buildDriveWay(rs->getNewDrivewayID(), myLink, firstIt, endIt);
576 : dw->setVehicle(info);
577 : #ifdef DEBUG_SELECT_DRIVEWAY
578 : std::cout << SIMTIME << " rs=" << getID() << " veh=" << info << " new dwSignal=" << dw->foundSignal() << " dwRoute=" << toString(dw->getRoute()) << "\n";
579 : #endif
580 5424 : myDriveways.push_back(dw);
581 5424 : return *myDriveways.back();
582 : }
583 :
584 :
585 : void
586 208265 : MSRailSignal::LinkInfo::reroute(SUMOVehicle* veh, const MSEdgeVector& occupied) {
587 208265 : MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
588 208265 : const SUMOTime now = MSNet::getInstance()->getCurrentTimeStep();
589 : if (rDev != nullptr
590 134616 : && rDev->mayRerouteRailSignal()
591 208424 : && (myLastRerouteVehicle != veh
592 : // reroute each vehicle only once if no periodic routing is allowed,
593 : // otherwise with the specified period
594 153 : || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
595 6 : myLastRerouteVehicle = veh;
596 6 : myLastRerouteTime = now;
597 :
598 : #ifdef DEBUG_REROUTE
599 : ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
600 : if (DEBUG_COND_LINKINFO) {
601 : std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
602 : }
603 : #endif
604 : MSRoutingEngine::Prohibitions prohibited;
605 18 : for (MSEdge* e : occupied) {
606 : // indefinite occupation because vehicles might be in deadlock on their current routes
607 12 : prohibited[e].end = std::numeric_limits<double>::max();
608 : }
609 18 : MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, prohibited);
610 : #ifdef DEBUG_REROUTE
611 : // attention this works only if we are not parallel!
612 : if (DEBUG_COND_LINKINFO) {
613 : if (veh->getRoute().getEdges() != oldRoute) {
614 : std::cout << " rerouting successful\n";
615 : }
616 : }
617 : #endif
618 : }
619 208265 : }
620 :
621 : void
622 18208 : MSRailSignal::resetStored() {
623 : myBlockingVehicles.clear();
624 : myRivalVehicles.clear();
625 : myPriorityVehicles.clear();
626 : myConstraintInfo = "";
627 : myBlockingDriveWays.clear();
628 : myRequestedDriveWay = "";
629 18208 : }
630 :
631 :
632 : void
633 0 : MSRailSignal::storeTraCIVehicles(const MSDriveWay* dw) {
634 0 : resetStored();
635 0 : myStoreVehicles = true;
636 : MSEdgeVector occupied;
637 : // call for side effects
638 0 : dw->foeDriveWayOccupied(true, nullptr, occupied);
639 0 : myStoreVehicles = false;
640 0 : }
641 :
642 : void
643 18208 : MSRailSignal::storeTraCIVehicles(int linkIndex) {
644 18208 : resetStored();
645 18208 : myStoreVehicles = true;
646 18208 : LinkInfo& li = myLinkInfos[linkIndex];
647 18208 : if (li.myLink->getApproaching().size() > 0) {
648 1825 : Approaching closest = li.myLink->getClosest();
649 1825 : MSDriveWay& driveway = li.getDriveWay(closest.first);
650 : MSEdgeVector occupied;
651 : myRequestedDriveWay = driveway.getID();
652 : // call for side effects
653 1825 : driveway.reserve(closest, occupied);
654 1825 : constraintsAllow(closest.first);
655 18208 : } else if (li.myDriveways.size() > 0) {
656 15891 : li.myDriveways.front()->conflictLaneOccupied();
657 15891 : li.myDriveways.front()->foeDriveWayApproached();
658 : }
659 18208 : myStoreVehicles = false;
660 18208 : }
661 :
662 : MSRailSignal::VehicleVector
663 6076 : MSRailSignal::getBlockingVehicles(int linkIndex) {
664 6076 : storeTraCIVehicles(linkIndex);
665 6076 : return myBlockingVehicles;
666 : }
667 :
668 : MSRailSignal::VehicleVector
669 6066 : MSRailSignal::getRivalVehicles(int linkIndex) {
670 6066 : storeTraCIVehicles(linkIndex);
671 6066 : return myRivalVehicles;
672 : }
673 :
674 : MSRailSignal::VehicleVector
675 6066 : MSRailSignal::getPriorityVehicles(int linkIndex) {
676 6066 : storeTraCIVehicles(linkIndex);
677 6066 : return myPriorityVehicles;
678 : }
679 :
680 : std::string
681 0 : MSRailSignal::getConstraintInfo(int linkIndex) {
682 0 : storeTraCIVehicles(linkIndex);
683 0 : return myConstraintInfo;
684 : }
685 :
686 :
687 : std::string
688 0 : MSRailSignal::getRequestedDriveWay(int linkIndex) {
689 0 : storeTraCIVehicles(linkIndex);
690 0 : return myRequestedDriveWay;
691 : }
692 :
693 :
694 : std::vector<const MSDriveWay*>
695 0 : MSRailSignal::getBlockingDriveWays(int linkIndex) {
696 0 : storeTraCIVehicles(linkIndex);
697 0 : return myBlockingDriveWays;
698 : }
699 :
700 :
701 : MSRailSignal::VehicleVector
702 0 : MSRailSignal::getBlockingVehicles(const MSDriveWay* dw) {
703 0 : storeTraCIVehicles(dw);
704 0 : return myBlockingVehicles;
705 : }
706 :
707 :
708 : std::vector<const MSDriveWay*>
709 0 : MSRailSignal::getBlockingDriveWays(const MSDriveWay* dw) {
710 0 : storeTraCIVehicles(dw);
711 0 : return myBlockingDriveWays;
712 : }
713 :
714 : const MSDriveWay&
715 0 : MSRailSignal::retrieveDriveWay(int numericalID) const {
716 0 : for (const LinkInfo& li : myLinkInfos) {
717 0 : for (const MSDriveWay* dw : li.myDriveways) {
718 0 : if (dw->getNumericalID() == numericalID) {
719 0 : return *dw;
720 : }
721 : }
722 : }
723 0 : throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
724 : }
725 :
726 : const MSDriveWay&
727 47372 : MSRailSignal::retrieveDriveWayForVeh(int tlIndex, const SUMOVehicle* veh) {
728 47372 : return myLinkInfos[tlIndex].getDriveWay(veh);
729 : }
730 :
731 : const MSDriveWay&
732 0 : MSRailSignal::retrieveDriveWayForRoute(int tlIndex, MSRouteIterator first, MSRouteIterator end) {
733 0 : return myLinkInfos[tlIndex].getDriveWay(first, end);
734 : }
735 :
736 :
737 : const std::vector<MSDriveWay*>
738 12569 : MSRailSignal::retrieveDriveWays(int tlIndex) const {
739 12569 : return myLinkInfos[tlIndex].myDriveways;
740 : }
741 :
742 :
743 : std::string
744 0 : MSRailSignal::getBlockingVehicleIDs() const {
745 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
746 0 : if (myLinkInfos.size() == 1) {
747 0 : return toString(rs->getBlockingVehicles(0));
748 : } else {
749 : std::string result;
750 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
751 0 : result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
752 : }
753 0 : return result;
754 : }
755 : }
756 : std::string
757 0 : MSRailSignal::getRivalVehicleIDs() const {
758 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
759 0 : if (myLinkInfos.size() == 1) {
760 0 : return toString(rs->getRivalVehicles(0));
761 : } else {
762 : std::string result;
763 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
764 0 : result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
765 : }
766 0 : return result;
767 : }
768 : }
769 : std::string
770 0 : MSRailSignal::getPriorityVehicleIDs() const {
771 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
772 0 : if (myLinkInfos.size() == 1) {
773 0 : return toString(rs->getPriorityVehicles(0));
774 : } else {
775 : std::string result;
776 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
777 0 : result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
778 : }
779 0 : return result;
780 : }
781 : }
782 : std::string
783 0 : MSRailSignal::getConstraintInfo() const {
784 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
785 0 : if (myLinkInfos.size() == 1) {
786 0 : return rs->getConstraintInfo(0);
787 : } else {
788 : std::string result;
789 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
790 0 : result += toString(i) + ": " + rs->getConstraintInfo(i);
791 : }
792 0 : return result;
793 : }
794 : }
795 : std::string
796 0 : MSRailSignal::getRequestedDriveWay() const {
797 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
798 0 : if (myLinkInfos.size() == 1) {
799 0 : return toString(rs->getRequestedDriveWay(0));
800 : } else {
801 : std::string result;
802 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
803 0 : result += toString(i) + ": " + toString(rs->getRequestedDriveWay(i)) + ";";
804 : }
805 0 : return result;
806 : }
807 : }
808 : std::string
809 0 : MSRailSignal::getBlockingDriveWayIDs() const {
810 : MSRailSignal* rs = const_cast<MSRailSignal*>(this);
811 0 : if (myLinkInfos.size() == 1) {
812 0 : return toString(rs->getBlockingDriveWays(0));
813 : } else {
814 : std::string result;
815 0 : for (int i = 0; i < (int)myLinkInfos.size(); i++) {
816 0 : result += toString(i) + ": " + toString(rs->getBlockingDriveWays(i)) + ";";
817 : }
818 0 : return result;
819 : }
820 : }
821 :
822 : void
823 5 : MSRailSignal::setParameter(const std::string& key, const std::string& value) {
824 : // some pre-defined parameters can be updated at runtime
825 5 : if (key == "moving-block") {
826 5 : bool movingBlock = StringUtils::toBool(value);
827 5 : if (movingBlock != myMovingBlock) {
828 : // recompute driveways
829 5 : myMovingBlock = movingBlock;
830 10 : for (LinkInfo& li : myLinkInfos) {
831 5 : li.reset();
832 : }
833 5 : updateCurrentPhase();
834 5 : setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
835 : }
836 : }
837 5 : Parameterised::setParameter(key, value);
838 5 : }
839 :
840 :
841 : std::string
842 5424 : MSRailSignal::getNewDrivewayID() {
843 10848 : return getID() + "." + toString(myDriveWayIndex++);
844 : }
845 : /****************************************************************************/
|