Eclipse SUMO - Simulation of Urban MObility
MSRailSignal.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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/****************************************************************************/
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
30#endif
33#include <microsim/MSNet.h>
34#include <microsim/MSEdge.h>
36#include <microsim/MSLane.h>
37#include <microsim/MSLink.h>
39#include <microsim/MSVehicle.h>
42#include <microsim/MSLane.h>
43
44#include "MSTLLogicControl.h"
45#include "MSTrafficLightLogic.h"
46#include "MSPhaseDefinition.h"
47#include "MSTLLogicControl.h"
49#include "MSRailSignalControl.h"
50#include "MSRailSignal.h"
51
52// typical block length in germany on main lines is 3-5km on branch lines up to 7km
53// special branches that are used by one train exclusively could also be up to 20km in length
54// minimum block size in germany is 37.5m (LZB)
55// larger countries (USA, Russia) might see blocks beyond 20km)
56#define MAX_BLOCK_LENGTH 20000
57#define MAX_SIGNAL_WARNINGS 10
58
59//#define DEBUG_BUILD_DRIVEWAY
60//#define DEBUG_CHECK_FLANKS
61//#define DEBUG_DRIVEWAY_BUILDROUTE
62//#define DEBUG_DRIVEWAY_UPDATE
63
64#define DEBUG_SIGNALSTATE
65#define DEBUG_SIGNALSTATE_PRIORITY
66#define DEBUG_FIND_PROTECTION
67//#define DEBUG_RECHECKGREEN
68//#define DEBUG_REROUTE
69
70#define DEBUG_COND DEBUG_HELPER(this)
71#define DEBUG_COND_LINKINFO DEBUG_HELPER(myLink->getTLLogic())
72#define DEBUG_HELPER(obj) ((obj)->isSelected())
73//#define DEBUG_HELPER(obj) ((obj)->getID() == "w2")
74//#define DEBUG_HELPER(obj) (true)
75
76// ===========================================================================
77// static value definitions
78// ===========================================================================
80
81std::vector<std::pair<MSLink*, int> > MSRailSignal::mySwitchedGreenFlanks;
82std::map<std::pair<int, int>, bool> MSRailSignal::myDriveWayCompatibility;
84
90
91// ===========================================================================
92// method definitions
93// ===========================================================================
95 const std::string& id, const std::string& programID, SUMOTime delay,
96 const Parameterised::Map& parameters) :
97 MSTrafficLightLogic(tlcontrol, id, programID, 0, TrafficLightType::RAIL_SIGNAL, delay, parameters),
98 myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')), // dummy phase
99 myPhaseIndex(0) {
101 myMovingBlock = OptionsCont::getOptions().getBool("railsignal-moving-block");
103}
104
105void
107 if (myLanes.size() == 0) {
108 WRITE_WARNINGF(TL("Rail signal at junction '%' does not control any links"), getID());
109 }
110 for (LinkVector& links : myLinks) { //for every link index
111 if (links.size() != 1) {
112 throw ProcessError("At railSignal '" + getID() + "' found " + toString(links.size())
113 + " links controlled by index " + toString(links[0]->getTLIndex()));
114 }
115 myLinkInfos.push_back(LinkInfo(links[0]));
116 }
118 setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
119 myNumLinks = (int)myLinks.size();
120}
121
122
125}
126
127
128// ----------- Handling of controlled links
129void
133}
134
135
136// ------------ Switching and setting current rows
140 return DELTA_T;
141}
142
143
144
145void
147#ifdef DEBUG_SIGNALSTATE
149#endif
150 // green by default so vehicles can be inserted at the borders of the network
151 std::string state(myLinks.size(), 'G');
152 for (LinkInfo& li : myLinkInfos) {
153 if (li.myLink->getApproaching().size() > 0) {
154 Approaching closest = getClosest(li.myLink);
155 DriveWay& driveway = li.getDriveWay(closest.first);
156 //std::cout << SIMTIME << " signal=" << getTLLinkID(li.myLink) << " veh=" << closest.first->getID() << " dw:\n";
157 //driveway.writeBlocks(*OutputDevice_COUT::getDevice());
158 const bool mustWait = !constraintsAllow(closest.first);
159 MSEdgeVector occupied;
160 if (mustWait || !driveway.reserve(closest, occupied)) {
161 state[li.myLink->getTLIndex()] = 'r';
162 if (occupied.size() > 0) {
163 li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
164 }
165#ifdef DEBUG_SIGNALSTATE
166 if (gDebugFlag4) {
167 std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " notReserved\n";
168 }
169#endif
170 } else {
171 state[li.myLink->getTLIndex()] = 'G';
172 if (driveway.myFlank.size() > 0 && myCurrentPhase.getState()[li.myLink->getTLIndex()] != 'G') {
173 // schedule recheck
174 mySwitchedGreenFlanks.push_back(std::make_pair(li.myLink, driveway.myNumericalID));
175 }
176#ifdef DEBUG_SIGNALSTATE
177 if (gDebugFlag4) {
178 std::cout << SIMTIME << " rsl=" << li.getID() << " veh=" << closest.first->getID() << " reserved\n";
179 }
180#endif
181 }
182 } else {
183 DriveWay& driveway = li.myDriveways.front();
184 if (driveway.conflictLaneOccupied() || driveway.conflictLinkApproached()) {
185#ifdef DEBUG_SIGNALSTATE
186 if (gDebugFlag4) {
187 std::cout << SIMTIME << " rsl=" << li.getID() << " red for default driveway (" << toString(driveway.myRoute) << ")\n";
188 }
189#endif
190 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 (" << toString(driveway.myRoute) << ")\n";
195 }
196#endif
197 }
198 }
199 }
200 if (myCurrentPhase.getState() != state) {
203 }
204#ifdef DEBUG_SIGNALSTATE
205 gDebugFlag4 = false;
206#endif
207}
208
209
210bool
212 if (myConstraints.size() == 0) {
213 return true;
214 } else {
215 const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
216 auto it = myConstraints.find(tripID);
217 if (it != myConstraints.end()) {
218 for (MSRailSignalConstraint* c : it->second) {
219 // ignore insertion constraints here
220 if (!c->isInsertionConstraint() && !c->cleared()) {
221#ifdef DEBUG_SIGNALSTATE
222 if (gDebugFlag4) {
223 std::cout << " constraint '" << c->getDescription() << "' not cleared\n";
224 }
225#endif
226 if (myStoreVehicles) {
228 }
229 return false;
230 }
231 }
232 }
233 return true;
234 }
235}
236
237
238void
239MSRailSignal::addConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
240 myConstraints[tripId].push_back(constraint);
241}
242
243
244bool
245MSRailSignal::removeConstraint(const std::string& tripId, MSRailSignalConstraint* constraint) {
246 if (myConstraints.count(tripId) != 0) {
247 auto& constraints = myConstraints[tripId];
248 auto it = std::find(constraints.begin(), constraints.end(), constraint);
249 if (it != constraints.end()) {
250 delete *it;
251 constraints.erase(it);
252 return true;
253 }
254 }
255 return false;
256}
257
258void
260 for (auto item : myConstraints) {
261 for (MSRailSignalConstraint* c : item.second) {
262 delete c;
263 }
264 }
265 myConstraints.clear();
266}
267
268
269// ------------ Static Information Retrieval
270int
272 return 0;
273}
274
277 return myPhases;
278}
279
282 return myCurrentPhase;
283}
284
285// ------------ Dynamic Information Retrieval
286int
288 return myPhaseIndex;
289}
290
293 return myCurrentPhase;
294}
295
296// ------------ Conversion between time and phase
299 return 0;
300}
301
304 return 0;
305}
306
307int
309 return 0;
310}
311
312
313void
314MSRailSignal::addLink(MSLink* link, MSLane* lane, int pos) {
315 if (pos >= 0) {
316 MSTrafficLightLogic::addLink(link, lane, pos);
317 } // ignore uncontrolled link
318}
319
320
321std::string
323 return link->getTLLogic()->getID() + "_" + toString(link->getTLIndex());
324}
325
326std::string
328 return link->getJunction()->getID() + "_" + toString(link->getIndex());
329}
330
331std::string
333 return "junction '" + link->getTLLogic()->getID() + "', link " + toString(link->getTLIndex());
334}
335
336std::string
337MSRailSignal::describeLinks(std::vector<MSLink*> links) {
338 std::string result;
339 for (MSLink* link : links) {
340 result += link->getDescription() + " ";
341 }
342 return result;
343}
344
345std::string
347 std::vector<const MSLane*> lanes(visited.size(), nullptr);
348 for (auto item : visited) {
349 lanes[item.second] = item.first;
350 }
351 return toString(lanes);
352}
353
354
355void
357 // avoid undefined behavior from evaluation order
358 const int tmp = (int)map.size();
359 map[lane] = tmp;
360}
361
362
365 assert(link->getApproaching().size() > 0);
366 double minDist = std::numeric_limits<double>::max();
367 auto closestIt = link->getApproaching().begin();
368 for (auto apprIt = link->getApproaching().begin(); apprIt != link->getApproaching().end(); apprIt++) {
369 if (apprIt->second.dist < minDist) {
370 minDist = apprIt->second.dist;
371 closestIt = apprIt;
372 }
373 }
374 // maybe a parallel link has a closer vehicle
375 /*
376 for (MSLink* link2 : link->getLaneBefore()->getLinkCont()) {
377 if (link2 != link) {
378 for (auto apprIt2 = link2->getApproaching().begin(); apprIt2 != link2->getApproaching().end(); apprIt2++) {
379 if (apprIt2->second.dist < minDist) {
380 minDist = apprIt2->second.dist;
381 closestIt = apprIt2;
382 }
383 }
384 }
385 }
386 */
387 return *closestIt;
388}
389
390
391void
393 od.openTag("railSignal");
395 for (const LinkInfo& li : myLinkInfos) {
396 MSLink* link = li.myLink;
397 od.openTag("link");
401 for (const DriveWay& dw : li.myDriveways) {
402 dw.writeBlocks(od);
403 }
404 od.closeTag(); // link
405 }
406 od.closeTag(); // railSignal
407}
408
409
410bool
411MSRailSignal::hasOncomingRailTraffic(MSLink* link, const MSVehicle* ego, bool& brakeBeforeSignal) {
412 // @note: this check is intended to prevent deadlock / collision by an inserted vehicle that
413 // waits at a red signal and thus checks different things than ::reverse()
414 bool hadOncoming = false;
416 const MSEdge* bidi = link->getLaneBefore()->getEdge().getBidiEdge();
417 if (bidi == nullptr) {
418 brakeBeforeSignal = false;
419 return false;
420 }
421 const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
422 if (rs != nullptr) {
423 const LinkInfo& li = rs->myLinkInfos[link->getTLIndex()];
424 for (const DriveWay& dw : li.myDriveways) {
425 //std::cout << SIMTIME <<< " hasOncomingRailTraffic link=" << getTLLinkID(link) << " dwRoute=" << toString(dw.myRoute) << " bidi=" << toString(dw.myBidi) << "\n";
426 for (MSLane* lane : dw.myBidi) {
427 if (!lane->isEmpty()) {
428#ifdef DEBUG_SIGNALSTATE
429 if (DEBUG_HELPER(rs)) {
430 std::cout << " oncoming vehicle on bidi-lane " << lane->getID() << "\n";
431 }
432#endif
433 return true;
434 }
435 }
436 for (const MSLane* lane : dw.myFlank) {
437 if (!lane->isEmpty()) {
438 MSVehicle* veh = lane->getFirstAnyVehicle();
439 if (std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), bidi) != veh->getRoute().end()) {
440#ifdef DEBUG_SIGNALSTATE
441 if (DEBUG_HELPER(rs)) {
442 std::cout << " oncoming vehicle on flank-lane " << lane->getID() << "\n";
443 }
444#endif
445 return true;
446 }
447 }
448 }
449 if (dw.myProtectingSwitchesBidi.size() > 0) {
450#ifdef DEBUG_SIGNALSTATE
452#endif
453 // yield to all foeLinks beyond switch
454 Approaching approaching(ego,
455 MSLink::ApproachingVehicleInformation(SUMOTime_MAX, 0, 0, 0, false, -1, 0, std::numeric_limits<double>::max(), 0, 0));
456 for (MSLink* const switchLink : dw.myProtectingSwitchesBidi) {
457 myBlockingVehicles.clear();
458 myRivalVehicles.clear();
459 myPriorityVehicles.clear();
460 myConstraintInfo = "";
461 myStoreVehicles = true;
462 const bool hasProtection = dw.findProtection(approaching, switchLink);
463 myStoreVehicles = false;
464 if (!hasProtection) {
465 for (const SUMOVehicle* veh : myBlockingVehicles) {
466 hadOncoming = true;
467 if (!brakeBeforeSignal || std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), bidi) != veh->getRoute().end()) {
468#ifdef DEBUG_SIGNALSTATE
469 if (DEBUG_HELPER(rs)) {
470 std::cout << " no protection at bidi-switch " << switchLink->getDescription() << " from veh=" << veh->getID() << "\n";
471 gDebugFlag4 = false;
472 }
473#endif
474 return true;
475 }
476 }
477 for (const SUMOVehicle* veh : myRivalVehicles) {
478 hadOncoming = true;
479 if (!brakeBeforeSignal || std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), bidi) != veh->getRoute().end()) {
480#ifdef DEBUG_SIGNALSTATE
481 if (DEBUG_HELPER(rs)) {
482 std::cout << " no protection at bidi-switch " << switchLink->getDescription() << " from linkRival veh=" << veh->getID() << "\n";
483 gDebugFlag4 = false;
484 }
485#endif
486 return true;
487 }
488 }
489 }
490 }
491#ifdef DEBUG_SIGNALSTATE
492 gDebugFlag4 = false;
493#endif
494 }
495 for (MSLink* foeLink : dw.myConflictLinks) {
496 if (foeLink->getApproaching().size() != 0) {
497 Approaching closest = getClosest(foeLink);
498 const SUMOVehicle* veh = closest.first;
499 if (veh->getSpeed() > 0 && closest.second.arrivalSpeedBraking > 0
500 && std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), bidi) != veh->getRoute().end()) {
501#ifdef DEBUG_SIGNALSTATE
502 if (DEBUG_HELPER(rs)) {
503 std::cout << " oncoming vehicle approaching foe link " << foeLink->getDescription() << "\n";
504 }
505#endif
506 return true;
507 }
508 }
509 }
510 }
511 }
512 }
513 brakeBeforeSignal = hadOncoming;
514 return false;
515}
516
517bool
518MSRailSignal::hasInsertionConstraint(MSLink* link, const MSVehicle* veh, std::string& info, bool& isInsertionOrder) {
519 if (link->getJunction() != nullptr && link->getJunction()->getType() == SumoXMLNodeType::RAIL_SIGNAL) {
520 const MSRailSignal* rs = dynamic_cast<const MSRailSignal*>(link->getTLLogic());
521 if (rs != nullptr && rs->myConstraints.size() > 0) {
522 const std::string tripID = veh->getParameter().getParameter("tripId", veh->getID());
523 auto it = rs->myConstraints.find(tripID);
524 if (it != rs->myConstraints.end()) {
525 for (MSRailSignalConstraint* c : it->second) {
526 if (c->isInsertionConstraint() && !c->cleared()) {
527#ifdef DEBUG_SIGNALSTATE
528 if (DEBUG_HELPER(rs)) {
529 std::cout << SIMTIME << " rsl=" << rs->getID() << " insertion constraint '" << c->getDescription() << "' for vehicle '" << veh->getID() << "' not cleared\n";
530 }
531#endif
532 info = c->getDescription();
533 isInsertionOrder = c->getType() == MSRailSignalConstraint::ConstraintType::INSERTION_ORDER;
534 return true;
535 }
536 }
537 }
538 }
539 }
540 return false;
541}
542
543// ===========================================================================
544// LinkInfo method definitions
545// ===========================================================================
546
548 myLink(link) {
549 reset();
550}
551
552
553void
555 myUniqueDriveWay = false;
556 myLastRerouteTime = -1;
557 myLastRerouteVehicle = nullptr;
558 myDriveways.clear();
559 ConstMSEdgeVector dummyRoute;
560 dummyRoute.push_back(&myLink->getLane()->getEdge());
561 DriveWay dw = buildDriveWay(dummyRoute.begin(), dummyRoute.end());
562 myDriveways.push_back(dw);
563}
564
565
566std::string
568 return myLink->getTLLogic()->getID() + "_" + toString(myLink->getTLIndex());
569}
570
571
574 if (myUniqueDriveWay) {
575 return myDriveways.front();
576 }
577 MSEdge* first = &myLink->getLane()->getEdge();
578 MSRouteIterator firstIt = std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), first);
579 if (firstIt == veh->getRoute().end()) {
580 // possibly the vehicle has already gone past the first edge (i.e.
581 // because first is short or the step-length is high)
582 // lets look backward along the route
583 // give some slack because the vehicle might have been braking from a higher speed and using ballistic integration
584 double lookBack = SPEED2DIST(veh->getSpeed() + 10);
585 int routeIndex = veh->getRoutePosition() - 1;
586 while (lookBack > 0 && routeIndex > 0) {
587 const MSEdge* prevEdge = veh->getRoute().getEdges()[routeIndex];
588 if (prevEdge == first) {
589 firstIt = veh->getRoute().begin() + routeIndex;
590 break;
591 }
592 lookBack -= prevEdge->getLength();
593 routeIndex--;
594 }
595 }
596 if (firstIt == veh->getRoute().end()) {
597 WRITE_WARNING("Invalid approach information to rail signal '" + getClickableTLLinkID(myLink) + "' after rerouting for vehicle '" + veh->getID()
598 + "' first driveway edge '" + first->getID() + "' time=" + time2string(MSNet::getInstance()->getCurrentTimeStep()) + ".");
599 return myDriveways.front();
600 }
601 //std::cout << SIMTIME << " veh=" << veh->getID() << " rsl=" << getID() << " dws=" << myDriveways.size() << "\n";
602 for (DriveWay& dw : myDriveways) {
603 // @todo optimize: it is sufficient to check for specific edges (after each switch)
604 auto itRoute = firstIt;
605 auto itDwRoute = dw.myRoute.begin();
606 bool match = true;
607 while (itRoute != veh->getRoute().end() && itDwRoute != dw.myRoute.end()) {
608 if (*itRoute != *itDwRoute) {
609 match = false;
610 //std::cout << " check dw=" << " match failed at vehEdge=" << (*itRoute)->getID() << " dwEdge=" << (*itDwRoute)->getID() << "\n";
611 break;
612 }
613 itRoute++;
614 itDwRoute++;
615 }
616 if (match) {
617 //std::cout << " using dw=" << "\n";
618 return dw;
619 }
620 }
621 DriveWay dw = buildDriveWay(firstIt, veh->getRoute().end());
622 myDriveways.push_back(dw);
623 return myDriveways.back();
624}
625
626
629 // collect lanes and links that are relevant for setting this signal for the current driveWay
630 // For each driveway we collect
631 // - conflictLanes (signal must be red if any conflict lane is occupied)
632 // - conflictLinks (signal must be red if any conflict link is approached by a vehicle
633 // - that cannot break in time (arrivalSpeedBraking > 0)
634 // - approached by a vehicle with higher switching priority (see #3941)
635 // These objects are construct in steps:
636 //
637 // forwardBlock
638 // - search forward recursive from outgoing lane until controlled railSignal link found
639 // -> add all found lanes to conflictLanes
640 //
641 // bidiBlock (if any forwardBlock edge has bidi edge)
642 // - search bidi backward recursive until first switch
643 // - from switch search backward recursive all other incoming until controlled rail signal link
644 // -> add final links to conflictLinks
645 //
646 // flanks
647 // - search backward recursive from flanking switches
648 // until controlled railSignal link or protecting switch is found
649 // -> add all found lanes to conflictLanes
650 // -> add final links to conflictLinks
651
652 DriveWay dw;
653 LaneVisitedMap visited;
654 std::vector<MSLane*> before;
655 appendMapIndex(visited, myLink->getLaneBefore());
656 MSLane* fromBidi = myLink->getLaneBefore()->getBidiLane();
657 if (fromBidi != nullptr) {
658 // do not extend to forward block beyond the entering track (in case of a loop)
659 appendMapIndex(visited, fromBidi);
660 before.push_back(fromBidi);
661 }
662 dw.buildRoute(myLink, 0., first, end, visited);
663 if (dw.myProtectedBidi == nullptr) {
664 dw.myCoreSize = (int)dw.myRoute.size();
665 }
666 dw.checkFlanks(dw.myForward, visited, true);
667 dw.checkFlanks(dw.myBidi, visited, false);
668 dw.checkFlanks(before, visited, true);
669
670 for (MSLink* link : dw.myFlankSwitches) {
671 //std::cout << getID() << " flankSwitch=" << link->getDescription() << "\n";
672 dw.findFlankProtection(link, 0, visited, link);
673 }
674
675#ifdef DEBUG_BUILD_DRIVEWAY
676 if (DEBUG_COND_LINKINFO || true) {
677 std::cout << " buildDriveWay railSignal=" << getID()
678 << "\n route=" << toString(dw.myRoute)
679 << "\n forward=" << toString(dw.myForward)
680 << "\n bidi=" << toString(dw.myBidi)
681 << "\n flank=" << toString(dw.myFlank)
682 << "\n flankSwitch=" << describeLinks(dw.myFlankSwitches)
683 << "\n protSwitch=" << describeLinks(dw.myProtectingSwitches)
684 << "\n coreSize=" << dw.myCoreSize
685 << "\n";
686 }
687#endif
688 MSRailSignal* rs = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(myLink->getTLLogic()));
689 if (!rs->myMovingBlock) {
690 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myForward.begin(), dw.myForward.end());
691 }
692 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myBidi.begin(), dw.myBidi.end());
693 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myFlank.begin(), dw.myFlank.end());
694 if (dw.myProtectedBidi != nullptr) {
696 }
697
698 return dw;
699}
700
701
702void
704 MSDevice_Routing* rDev = static_cast<MSDevice_Routing*>(veh->getDevice(typeid(MSDevice_Routing)));
706 if (rDev != nullptr
707 && rDev->mayRerouteRailSignal()
708 && (myLastRerouteVehicle != veh
709 // reroute each vehicle only once if no periodic routing is allowed,
710 // otherwise with the specified period
711 || (rDev->getPeriod() > 0 && myLastRerouteTime + rDev->getPeriod() <= now))) {
712 myLastRerouteVehicle = veh;
713 myLastRerouteTime = now;
714
715#ifdef DEBUG_REROUTE
716 ConstMSEdgeVector oldRoute = veh->getRoute().getEdges();
718 std::cout << SIMTIME << " reroute veh=" << veh->getID() << " rs=" << getID() << " occupied=" << toString(occupied) << "\n";
719 }
720#endif
721 MSRoutingEngine::reroute(*veh, now, "railSignal:" + getID(), false, true, occupied);
722#ifdef DEBUG_REROUTE
723 // attention this works only if we are not parallel!
725 if (veh->getRoute().getEdges() != oldRoute) {
726 std::cout << " rerouting successful\n";
727 }
728 }
729#endif
730 }
731}
732
733
734// ===========================================================================
735// DriveWay method definitions
736// ===========================================================================
737
738bool
740 std::string joinVehicle = "";
742 const SUMOVehicleParameter::Stop* stop = closest.first->getNextStopParameter();
743 if (stop != nullptr) {
744 joinVehicle = stop->join;
745 }
746 }
747 if (conflictLaneOccupied(joinVehicle)) {
748 for (MSLane* bidi : myBidi) {
749 if (!bidi->empty() && bidi->getBidiLane() != nullptr) {
750 occupied.push_back(&bidi->getBidiLane()->getEdge());
751 }
752 }
753#ifdef DEBUG_SIGNALSTATE
754 if (gDebugFlag4) {
755 std::cout << " conflictLaneOccupied\n";
756 }
757#endif
758 return false;
759 }
760 for (MSLink* link : myProtectingSwitches) {
761 if (!findProtection(closest, link)) {
762#ifdef DEBUG_SIGNALSTATE
763 if (gDebugFlag4) {
764 std::cout << " no protection at switch " << link->getDescription() << "\n";
765 }
766#endif
767 return false;
768 }
769 }
770 for (MSLink* foeLink : myConflictLinks) {
771 if (hasLinkConflict(closest, foeLink)) {
772#ifdef DEBUG_SIGNALSTATE
773 if (gDebugFlag4) {
774 std::cout << " linkConflict with " << getTLLinkID(foeLink) << "\n";
775 }
776#endif
777 return false;
778 }
779 }
780 if (deadlockLaneOccupied()) {
781 return false;
782 }
783 myActive = closest.first;
784 return true;
785}
786
787
788bool
790 for (MSLink* foeLink : myConflictLinks) {
791 if (foeLink->getApproaching().size() > 0) {
792#ifdef DEBUG_SIGNALSTATE
793 if (gDebugFlag4) {
794 std::cout << SIMTIME << " foeLink=" << foeLink->getDescription() << " approachedBy=" << foeLink->getApproaching().begin()->first->getID() << "\n";
795 }
796#endif
797 return true;
798 }
799 }
800 return false;
801}
802
803
804bool
806#ifdef DEBUG_SIGNALSTATE_PRIORITY
807 if (gDebugFlag4) {
808 std::cout << " checkLinkConflict foeLink=" << getTLLinkID(foeLink) << "\n";
809 }
810#endif
811 if (foeLink->getApproaching().size() > 0) {
812 Approaching foe = getClosest(foeLink);
813#ifdef DEBUG_SIGNALSTATE_PRIORITY
814 if (gDebugFlag4) {
815 std::cout << " approaching foe=" << foe.first->getID() << "\n";
816 }
817#endif
818 const MSTrafficLightLogic* foeTLL = foeLink->getTLLogic();
819 assert(foeTLL != nullptr);
820 const MSRailSignal* constFoeRS = dynamic_cast<const MSRailSignal*>(foeTLL);
821 MSRailSignal* foeRS = const_cast<MSRailSignal*>(constFoeRS);
822 if (foeRS != nullptr) {
823 const DriveWay& foeDriveWay = foeRS->myLinkInfos[foeLink->getTLIndex()].getDriveWay(foe.first);
824 if (foeDriveWay.conflictLaneOccupied("", false) ||
825 foeDriveWay.deadlockLaneOccupied(false) ||
826 !foeRS->constraintsAllow(foe.first) ||
827 !overlap(foeDriveWay)) {
828#ifdef DEBUG_SIGNALSTATE_PRIORITY
829 if (gDebugFlag4) {
830 if (foeDriveWay.conflictLaneOccupied("", false)) {
831 std::cout << " foe blocked\n";
832 } else if (!foeRS->constraintsAllow(foe.first)) {
833 std::cout << " foe constrained\n";
834 } else {
835 std::cout << " no overlap\n";
836 }
837 }
838#endif
839 return false;
840 }
841#ifdef DEBUG_SIGNALSTATE_PRIORITY
842 if (gDebugFlag4) {
843 std::cout
844 << " aSB=" << veh.second.arrivalSpeedBraking << " foeASB=" << foe.second.arrivalSpeedBraking
845 << " aT=" << veh.second.arrivalTime << " foeAT=" << foe.second.arrivalTime
846 << " aS=" << veh.first->getSpeed() << " foeS=" << foe.first->getSpeed()
847 << " aD=" << veh.second.dist << " foeD=" << foe.second.dist
848 << " aW=" << veh.first->getWaitingTime() << " foeW=" << foe.first->getWaitingTime()
849 << " aN=" << veh.first->getNumericalID() << " foeN=" << foe.first->getNumericalID()
850 << "\n";
851 }
852#endif
853 const bool yield = mustYield(veh, foe);
854 if (myStoreVehicles) {
855 myRivalVehicles.push_back(foe.first);
856 if (yield) {
857 myPriorityVehicles.push_back(foe.first);
858 }
859 }
860 return yield;
861 }
862 }
863 return false;
864}
865
866
867bool
869 if (foe.second.arrivalSpeedBraking == veh.second.arrivalSpeedBraking) {
870 if (foe.second.arrivalTime == veh.second.arrivalTime) {
871 if (foe.first->getSpeed() == veh.first->getSpeed()) {
872 if (foe.second.dist == veh.second.dist) {
873 if (foe.first->getWaitingTime() == veh.first->getWaitingTime()) {
874 return foe.first->getNumericalID() < veh.first->getNumericalID();
875 } else {
876 return foe.first->getWaitingTime() > veh.first->getWaitingTime();
877 }
878 } else {
879 return foe.second.dist < veh.second.dist;
880 }
881 } else {
882 return foe.first->getSpeed() > veh.first->getSpeed();
883 }
884 } else {
885 return foe.second.arrivalTime < veh.second.arrivalTime;
886 }
887 } else {
888 return foe.second.arrivalSpeedBraking > veh.second.arrivalSpeedBraking;
889 }
890}
891
892
893bool
894MSRailSignal::DriveWay::conflictLaneOccupied(const std::string& joinVehicle, bool store) const {
895 for (const MSLane* lane : myConflictLanes) {
896 if (!lane->isEmpty()) {
897#ifdef DEBUG_SIGNALSTATE
898 if (gDebugFlag4) {
899 std::cout << SIMTIME << " conflictLane " << lane->getID() << " occupied\n";
900 if (joinVehicle != "") {
901 std::cout << " joinVehicle=" << joinVehicle << " occupant=" << toString(lane->getVehiclesSecure()) << "\n";
902 lane->releaseVehicles();
903 }
904 }
905#endif
906 if (lane->getVehicleNumber() == 1 && joinVehicle != "") {
907 std::vector<MSVehicle*> vehs = lane->getVehiclesSecure();
908 const bool ignoreJoinTarget = vehs.front()->getID() == joinVehicle && vehs.front()->isStopped();
909 lane->releaseVehicles();
910 if (ignoreJoinTarget) {
911#ifdef DEBUG_SIGNALSTATE
912 if (gDebugFlag4) {
913 std::cout << " ignore join-target '" << joinVehicle << ";\n";
914 }
915#endif
916 continue;
917 }
918 }
919 if (myStoreVehicles && store) {
920 myBlockingVehicles.push_back(lane->getLastAnyVehicle());
921 }
922 return true;
923 }
924 }
925 return false;
926}
927
928bool
930 for (MSLane* lane : myBidiExtended) {
931 if (!lane->empty()) {
932 assert(myBidi.size() != 0);
933 const MSEdge* lastBidi = myBidi.back()->getNextNormal();
934 MSVehicle* foe = lane->getVehiclesSecure().front();
935#ifdef DEBUG_SIGNALSTATE
936 if (gDebugFlag4) {
937 std::cout << " check for deadlock with " << foe->getID() << "\n";
938 }
939#endif
940 // check of foe will enter myBidi (need to check at most
941 // myBidiExtended.size edges)
942 const int minEdges = (int)myBidiExtended.size();
943 auto foeIt = foe->getCurrentRouteEdge() + 1;
944 auto foeEnd = foe->getRoute().end();
945 bool conflict = false;
946 for (int i = 0; i < minEdges && foeIt != foeEnd; i++) {
947 if ((*foeIt) == lastBidi) {
948#ifdef DEBUG_SIGNALSTATE
949 if (gDebugFlag4) {
950 std::cout << " vehicle will enter " << lastBidi->getID() << "\n";
951 }
952#endif
953 conflict = true;
954 break;
955 }
956 foeIt++;
957 }
958 lane->releaseVehicles();
959 if (conflict) {
960 if (myStoreVehicles && store) {
961 myBlockingVehicles.push_back(foe);
962 }
963 return true;
964 }
965 }
966 }
967 return false;
968}
969
970
971bool
973 double flankApproachingDist = std::numeric_limits<double>::max();
974 if (link->getApproaching().size() > 0) {
975 Approaching closest = getClosest(link);
976 flankApproachingDist = closest.second.dist;
977 }
978#ifdef DEBUG_FIND_PROTECTION
979 if (gDebugFlag4) {
980 std::cout << SIMTIME << " findProtection for link=" << link->getDescription() << " flankApproachingDist=" << flankApproachingDist << "\n";
981 }
982#endif
983 for (MSLink* l2 : link->getLaneBefore()->getLinkCont()) {
984 if (l2->getLane() != link->getLane()) {
985#ifdef DEBUG_FIND_PROTECTION
986 if (gDebugFlag4) {
987 std::cout << " protectionCandidate=" << l2->getDescription() << " l2Via=" << Named::getIDSecure(l2->getViaLane())
988 << " occupied=" << (l2->getViaLane() != nullptr && !l2->getViaLane()->isEmpty()) << "\n";
989 }
990#endif
991 if (l2->getViaLane() != nullptr && !l2->getViaLane()->isEmpty()) {
992#ifdef DEBUG_FIND_PROTECTION
993 if (gDebugFlag4) {
994 std::cout << " protection from internal=" << l2->getViaLane()->getID() << "\n";
995 }
996#endif
997 return true;
998 }
999 if (l2->getApproaching().size() > 0) {
1000 Approaching closest2 = getClosest(l2);
1001 if (closest2.second.dist < flankApproachingDist) {
1002#ifdef DEBUG_FIND_PROTECTION
1003 if (gDebugFlag4) {
1004 std::cout << " protection from veh=" << closest2.first->getID() << "\n";
1005 }
1006#endif
1007 return true;
1008 }
1009 }
1010 }
1011 }
1012 if (link->getApproaching().size() == 0) {
1013 return true;
1014 } else {
1015 // find protection further upstream
1016 DriveWay tmp(true);
1017 const MSLane* before = link->getLaneBefore();
1018 tmp.myFlank.push_back(before);
1019 LaneVisitedMap visited;
1020 for (auto ili : before->getIncomingLanes()) {
1021 tmp.findFlankProtection(ili.viaLink, myMaxFlankLength, visited, ili.viaLink);
1022 }
1023 tmp.myConflictLanes = tmp.myFlank;
1024 tmp.myRoute = myRoute;
1025 tmp.myCoreSize = myCoreSize;
1026 MSEdgeVector occupied;
1027 if (gDebugFlag4) std::cout << SIMTIME << " tmpDW flank=" << toString(tmp.myFlank)
1028 << " protSwitch=" << describeLinks(tmp.myProtectingSwitches) << " cLinks=" << describeLinks(tmp.myConflictLinks) << "\n";
1029 return tmp.reserve(veh, occupied);
1030 }
1031}
1032
1033
1034bool
1036 for (int i = 0; i < myCoreSize; i++) {
1037 for (int j = 0; j < other.myCoreSize; j++) {
1038 const MSEdge* edge = myRoute[i];
1039 const MSEdge* edge2 = other.myRoute[j];
1040 if (edge->getToJunction() == edge2->getToJunction()
1041 || edge->getToJunction() == edge2->getFromJunction()) {
1042 // XXX might be rail_crossing with parallel tracks
1043 return true;
1044 }
1045 }
1046 }
1047 return false;
1048}
1049
1050bool
1052 for (const MSLane* lane : myForward) {
1053 for (const MSLane* lane2 : other.myForward) {
1054 if (lane == lane2) {
1055 return true;
1056 }
1057 }
1058 for (const MSLane* lane2 : other.myBidi) {
1059 if (lane == lane2) {
1060 return true;
1061 }
1062 }
1063 }
1064 return false;
1065}
1066
1067void
1069 od.openTag("driveWay");
1070 od.writeAttr(SUMO_ATTR_EDGES, toString(myRoute));
1071 if (myCoreSize != (int)myRoute.size()) {
1072 od.writeAttr("core", myCoreSize);
1073 }
1074 od.openTag("forward");
1075 od.writeAttr(SUMO_ATTR_LANES, toString(myForward));
1076 od.closeTag();
1077 od.openTag("bidi");
1078 od.writeAttr(SUMO_ATTR_LANES, toString(myBidi));
1079 if (myBidiExtended.size() > 0) {
1080 od.lf();
1081 od << " ";
1082 od.writeAttr("deadlockCheck", toString(myBidiExtended));
1083 }
1084 od.closeTag();
1085 od.openTag("flank");
1086 od.writeAttr(SUMO_ATTR_LANES, toString(myFlank));
1087 od.closeTag();
1088
1089 od.openTag("protectingSwitches");
1090 std::vector<std::string> links;
1091 for (MSLink* link : myProtectingSwitches) {
1092 links.push_back(getJunctionLinkID(link));
1093 }
1094 od.writeAttr("links", joinToString(links, " "));
1095 od.closeTag();
1096
1097 od.openTag("conflictLinks");
1098 std::vector<std::string> signals;
1099 for (MSLink* link : myConflictLinks) {
1100 signals.push_back(getTLLinkID(link));
1101 }
1102 od.writeAttr("signals", joinToString(signals, " "));
1103 od.closeTag();
1104 od.closeTag(); // driveWay
1105}
1106
1107
1108void
1111 LaneVisitedMap& visited) {
1112 bool seekForwardSignal = true;
1113 bool seekBidiSwitch = true;
1114 bool foundUnsafeSwitch = false;
1115 MSLane* toLane = origin->getViaLaneOrLane();
1116#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1117 gDebugFlag4 = true; //getClickableTLLinkID(origin) == "junction 's24', link 0";
1118 if (gDebugFlag4) std::cout << "buildRoute origin=" << getTLLinkID(origin) << " vehRoute=" << toString(ConstMSEdgeVector(next, end))
1119 << " visited=" << formatVisitedMap(visited) << "\n";
1120#endif
1121 while ((seekForwardSignal || seekBidiSwitch)) {
1122 if (length > MAX_BLOCK_LENGTH) {
1124 WRITE_WARNING("Block after rail signal " + getClickableTLLinkID(origin) +
1125 " exceeds maximum length (stopped searching after edge '" + toLane->getEdge().getID() + "' (length=" + toString(length) + "m).");
1126 }
1127 myNumWarnings++;
1128 // length exceeded
1129 return;
1130 }
1131#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1132 if (gDebugFlag4) {
1133 std::cout << " toLane=" << toLane->getID() << " visited=" << formatVisitedMap(visited) << "\n";
1134 }
1135#endif
1136 if (visited.count(toLane) != 0) {
1137 WRITE_WARNING("Found circular block after railSignal " + getClickableTLLinkID(origin) + " (" + toString(myRoute.size()) + " edges, length " + toString(length) + ")");
1138 //std::cout << getClickableTLLinkID(origin) << " circularBlock1=" << toString(myRoute) << " visited=" << formatVisitedMap(visited) << "\n";
1139 return;
1140 }
1141 if (toLane->getEdge().isNormal()) {
1142 myRoute.push_back(&toLane->getEdge());
1143 if (next != end) {
1144 next++;
1145 }
1146 }
1147 appendMapIndex(visited, toLane);
1148 length += toLane->getLength();
1149 MSLane* bidi = toLane->getBidiLane();
1150 if (seekForwardSignal) {
1151 if (!foundUnsafeSwitch) {
1152 myForward.push_back(toLane);
1153 }
1154 } else if (bidi == nullptr) {
1155 seekBidiSwitch = false;
1156#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1157 if (gDebugFlag4) {
1158 std::cout << " noBidi, abort search for bidiSwitch\n";
1159 }
1160#endif
1161 }
1162 if (bidi != nullptr) {
1163 if (foundUnsafeSwitch) {
1164 myBidiExtended.push_back(bidi);
1165 } else {
1166 myBidi.push_back(bidi);
1167 }
1168 appendMapIndex(visited, bidi);
1169 if (!seekForwardSignal) {
1170 // look for switch that could protect from oncoming vehicles
1171 for (const auto& ili : bidi->getIncomingLanes()) {
1172 if (ili.viaLink->getDirection() == LinkDirection::TURN) {
1173 continue;
1174 }
1175 for (const MSLink* const link : ili.lane->getLinkCont()) {
1176 if (link->getDirection() == LinkDirection::TURN) {
1177 continue;
1178 }
1179 if (link->getViaLaneOrLane() != bidi) {
1180 // this switch is special beause it still lies on the current route
1181 //myProtectingSwitches.push_back(ili.viaLink);
1182 const MSEdge* const bidiNext = bidi->getNextNormal();
1183 myCoreSize = (int)myRoute.size();
1184 if (MSRailSignalControl::getInstance().getUsedEdges().count(bidiNext) == 0) {
1185#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1186 if (gDebugFlag4) {
1187 std::cout << " abort: found protecting switch " << ili.viaLink->getDescription() << "\n";
1188 }
1189#endif
1190 // if bidi is actually used by a train (rather than
1191 // the other route) we must later adapt this driveway for additional checks (myBidiExtended)
1192 myProtectedBidi = bidiNext;
1193 return;
1194 } else {
1195#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1196 if (gDebugFlag4) {
1197 std::cout << " found unsafe switch " << ili.viaLink->getDescription() << " (used=" << bidiNext->getID() << ")\n";
1198 }
1199#endif
1200 // trains along our route beyond this switch
1201 // might create deadlock
1202 foundUnsafeSwitch = true;
1203 // the switch itself must still be guarded to ensure safety
1204 for (const auto& ili2 : bidi->getIncomingLanes()) {
1205 if (ili2.viaLink->getDirection() != LinkDirection::TURN) {
1206 myFlankSwitches.push_back(ili.viaLink);
1207 }
1208 }
1209 }
1210 }
1211 }
1212 }
1213 }
1214 }
1215 const std::vector<MSLink*>& links = toLane->getLinkCont();
1216 const MSEdge* current = &toLane->getEdge();
1217 toLane = nullptr;
1218 for (const MSLink* const link : links) {
1219 if (((next != end && &link->getLane()->getEdge() == *next) ||
1220 (next == end && link->getDirection() != LinkDirection::TURN))
1221 && isRailway(link->getViaLaneOrLane()->getPermissions())) {
1222 toLane = link->getViaLaneOrLane();
1223 if (link->getLane()->getBidiLane() != nullptr && &link->getLane()->getEdge() == current->getBidiEdge()) {
1224 // do not follow turn-arounds even if the route contains a reversal
1225#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1226 if (gDebugFlag4) {
1227 std::cout << " abort: turn-around\n";
1228 }
1229#endif
1230 return;
1231 }
1232 if (link->getTLLogic() != nullptr) {
1233 if (link->getTLLogic() == origin->getTLLogic()) {
1234 WRITE_WARNING("Found circular block at railSignal " + getClickableTLLinkID(origin) + " (" + toString(myRoute.size()) + " edges, length " + toString(length) + ")");
1235 //std::cout << getClickableTLLinkID(origin) << " circularBlock2=" << toString(myRoute) << "\n";
1236 return;
1237 }
1238 seekForwardSignal = false;
1239 seekBidiSwitch = bidi != nullptr;
1240#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1241 if (gDebugFlag4) {
1242 std::cout << " found forwardSignal " << link->getTLLogic()->getID() << " seekBidiSwitch=" << seekBidiSwitch << "\n";
1243 }
1244#endif
1245 }
1246 break;
1247 }
1248 }
1249 if (toLane == nullptr) {
1250 if (next != end) {
1251 // no connection found, jump to next route edge
1252 toLane = (*next)->getLanes()[0];
1253 } else {
1254#ifdef DEBUG_DRIVEWAY_BUILDROUTE
1255 if (gDebugFlag4) {
1256 std::cout << " abort: no next lane available\n";
1257 }
1258#endif
1259 return;
1260 }
1261 }
1262 }
1263}
1264
1265
1266void
1267MSRailSignal::DriveWay::checkFlanks(const std::vector<MSLane*>& lanes, const LaneVisitedMap& visited, bool allFoes) {
1268#ifdef DEBUG_CHECK_FLANKS
1269 std::cout << " checkFlanks lanes=" << toString(lanes) << "\n visited=" << formatVisitedMap(visited) << " allFoes=" << allFoes << "\n";
1270#endif
1271 for (MSLane* lane : lanes) {
1272 if (lane->isInternal()) {
1273 continue;
1274 }
1275 for (auto ili : lane->getIncomingLanes()) {
1276 if (visited.count(ili.lane->getNormalPredecessorLane()) == 0) {
1277#ifdef DEBUG_CHECK_FLANKS
1278 std::cout << " add flankSwitch junction=" << ili.viaLink->getJunction()->getID() << " index=" << ili.viaLink->getIndex() << "\n";
1279#endif
1280 myFlankSwitches.push_back(ili.viaLink);
1281 } else if (allFoes) {
1282 // link is part of the driveway, find foes that cross the driveway without entering
1283 checkCrossingFlanks(ili.viaLink, visited);
1284 }
1285 }
1286 }
1287}
1288
1289
1290void
1292#ifdef DEBUG_CHECK_FLANKS
1293 std::cout << " checkCrossingFlanks dwLink=" << dwLink->getDescription() << " visited=" << formatVisitedMap(visited) << "\n";
1294#endif
1295 const MSJunction* junction = dwLink->getJunction();
1296 if (junction == nullptr) {
1297 return; // unregulated junction;
1298 }
1299 const MSJunctionLogic* logic = junction->getLogic();
1300 if (logic == nullptr) {
1301 return; // unregulated junction;
1302 }
1303 for (const MSEdge* in : junction->getIncoming()) {
1304 if (in->isInternal()) {
1305 continue;
1306 }
1307 for (MSLane* inLane : in->getLanes()) {
1308 if (isRailway(inLane->getPermissions()) && visited.count(inLane) == 0) {
1309 for (MSLink* link : inLane->getLinkCont()) {
1310 if (link->getIndex() >= 0 && logic->getFoesFor(dwLink->getIndex()).test(link->getIndex())
1311 && visited.count(link->getLane()) == 0) {
1312#ifdef DEBUG_CHECK_FLANKS
1313 std::cout << " add crossing flankSwitch junction=" << junction->getID() << " index=" << link->getIndex() << "\n";
1314#endif
1315 if (link->getViaLane() == nullptr) {
1316 myFlankSwitches.push_back(link);
1317 } else {
1318 myFlankSwitches.push_back(link->getViaLane()->getLinkCont().front());
1319 }
1320 }
1321 }
1322 }
1323 }
1324 }
1325}
1326
1327void
1329#ifdef DEBUG_CHECK_FLANKS
1330 std::cout << " findFlankProtection link=" << link->getDescription() << " length=" << length << " origLink=" << origLink->getDescription() << "\n";
1331#endif
1332 if (link->getTLLogic() != nullptr) {
1333 // guarded by signal
1334#ifdef DEBUG_CHECK_FLANKS
1335 std::cout << " flank guarded by " << link->getTLLogic()->getID() << "\n";
1336#endif
1337 myConflictLinks.push_back(link);
1338 } else if (length > MAX_BLOCK_LENGTH) {
1339 // length exceeded
1341 WRITE_WARNING("Incoming block at junction '" + origLink->getJunction()->getID() + "', link " + toString(origLink->getIndex()) + " exceeds maximum length (stopped searching after lane '" + link->getLane()->getID() + "' (length=" + toString(length) + "m).");
1342 }
1343 myNumWarnings++;
1344 } else {
1345 // find normal lane before this link
1346 const MSLane* lane = link->getLaneBefore();
1347 const bool isNew = visited.count(lane) == 0;
1348 if (isNew || (visited[lane] > visited[origLink->getLane()] && std::find(myForward.begin(), myForward.end(), lane) == myForward.end())) {
1349 if (isNew) {
1350 appendMapIndex(visited, lane);
1351 }
1352 length += lane->getLength();
1353 if (lane->isInternal()) {
1354 myFlank.push_back(lane);
1355 findFlankProtection(lane->getIncomingLanes().front().viaLink, length, visited, origLink);
1356 } else {
1357 bool foundPSwitch = false;
1358 for (MSLink* l2 : lane->getLinkCont()) {
1359#ifdef DEBUG_CHECK_FLANKS
1360 std::cout << " lane=" << lane->getID() << " visitedIndex=" << visited[lane] << " origIndex=" << visited[origLink->getLane()] << " cand=" << l2->getDescription() << "\n";
1361#endif
1362 if (l2->getDirection() != LinkDirection::TURN && l2->getLane() != link->getLane()) {
1363 foundPSwitch = true;
1364 // found potential protection
1365#ifdef DEBUG_CHECK_FLANKS
1366 std::cout << " protectingSwitch=" << l2->getDescription() << " for flank=" << link->getDescription() << "\n";
1367#endif
1368 myProtectingSwitches.push_back(link);
1369 if (std::find(myBidi.begin(), myBidi.end(), origLink->getLane()) != myBidi.end()) {
1370#ifdef DEBUG_CHECK_FLANKS
1371 std::cout << " (is bidi-switch)\n";
1372#endif
1373 myProtectingSwitchesBidi.push_back(link);
1374 }
1375 }
1376 }
1377 if (!foundPSwitch) {
1378 myFlank.push_back(lane);
1379 // continue search for protection upstream recursively
1380 for (auto ili : lane->getIncomingLanes()) {
1381 if (ili.viaLink->getDirection() != LinkDirection::TURN) {
1382 findFlankProtection(ili.viaLink, length, visited, origLink);
1383 }
1384 }
1385 }
1386 }
1387 } else {
1388#ifdef DEBUG_CHECK_FLANKS
1389 std::cout << " laneBefore=" << lane->getID() << " already visited. index=" << visited[lane] << " origAfter=" << origLink->getLane()->getID() << " origIndex=" << visited[origLink->getLane()] << "\n";
1390#endif
1391 }
1392 }
1393 myMaxFlankLength = MAX2(myMaxFlankLength, length);
1394}
1395
1396void
1398 myBlockingVehicles.clear();
1399 myRivalVehicles.clear();
1400 myPriorityVehicles.clear();
1401 myConstraintInfo = "";
1402 myStoreVehicles = true;
1403 LinkInfo& li = myLinkInfos[linkIndex];
1404 if (li.myLink->getApproaching().size() > 0) {
1405 Approaching closest = getClosest(li.myLink);
1406 DriveWay& driveway = li.getDriveWay(closest.first);
1407 MSEdgeVector occupied;
1408 // call for side effects
1409 driveway.reserve(closest, occupied);
1410 constraintsAllow(closest.first);
1411 } else {
1412 li.myDriveways.front().conflictLaneOccupied();
1413 }
1414 myStoreVehicles = false;
1415}
1416
1419 storeTraCIVehicles(linkIndex);
1420 return myBlockingVehicles;
1421}
1422
1425 storeTraCIVehicles(linkIndex);
1426 return myRivalVehicles;
1427}
1428
1431 storeTraCIVehicles(linkIndex);
1432 return myPriorityVehicles;
1433}
1434
1435std::string
1437 storeTraCIVehicles(linkIndex);
1438 return myConstraintInfo;
1439}
1440
1442MSRailSignal::retrieveDriveWay(int numericalID) const {
1443 for (const LinkInfo& li : myLinkInfos) {
1444 for (const DriveWay& dw : li.myDriveways) {
1445 if (dw.myNumericalID == numericalID) {
1446 return dw;
1447 }
1448 }
1449 }
1450 throw ProcessError("Invalid driveway id " + toString(numericalID) + " at railSignal '" + getID() + "'");
1451}
1452
1453
1454void
1456 if (mySwitchedGreenFlanks.size() > 0) {
1457 for (const auto& item : mySwitchedGreenFlanks) {
1458 for (const auto& item2 : mySwitchedGreenFlanks) {
1459 if (item.second < item2.second) {
1460 bool conflict = false;
1461 std::pair<int, int> code(item.second, item2.second);
1462 auto it = myDriveWayCompatibility.find(code);
1463 if (it != myDriveWayCompatibility.end()) {
1464 conflict = it->second;
1465 } else {
1466 // new driveway pair
1467 const MSRailSignal* rs = static_cast<const MSRailSignal*>(item.first->getTLLogic());
1468 const MSRailSignal* rs2 = static_cast<const MSRailSignal*>(item2.first->getTLLogic());
1469 const DriveWay& dw = rs->retrieveDriveWay(item.second);
1470 const DriveWay& dw2 = rs2->retrieveDriveWay(item2.second);
1471 // overlap may return true if the driveways are consecutive forward sections
1472 conflict = dw.flankConflict(dw2) || dw2.flankConflict(dw);
1473 myDriveWayCompatibility[code] = conflict;
1474#ifdef DEBUG_RECHECKGREEN
1475 std::cout << SIMTIME << " new code " << code.first << "," << code.second << " conflict=" << conflict << " dw=" << toString(dw.myRoute) << " dw2=" << toString(dw2.myRoute) << "\n";
1476#endif
1477 }
1478 if (conflict) {
1479 MSRailSignal* rs = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item.first->getTLLogic()));
1480 MSRailSignal* rs2 = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item2.first->getTLLogic()));
1481 const Approaching& veh = rs->getClosest(item.first);
1482 const Approaching& veh2 = rs2->getClosest(item2.first);
1483 if (DriveWay::mustYield(veh, veh2)) {
1484 std::string state = rs->myCurrentPhase.getState();
1485 state[item.first->getTLIndex()] = 'r';
1486 rs->myCurrentPhase.setState(state);
1488#ifdef DEBUG_RECHECKGREEN
1489 std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first)
1490 << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n";
1491#endif
1492#ifdef DEBUG_SIGNALSTATE
1493 if (DEBUG_HELPER(rs)) {
1494 std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first)
1495 << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n";
1496 }
1497#endif
1498 } else {
1499 std::string state = rs2->myCurrentPhase.getState();
1500 state[item2.first->getTLIndex()] = 'r';
1501 rs2->myCurrentPhase.setState(state);
1502 rs2->setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
1503#ifdef DEBUG_RECHECKGREEN
1504 std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first)
1505 << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n";
1506#endif
1507#ifdef DEBUG_SIGNALSTATE
1508 if (DEBUG_HELPER(rs2)) {
1509 std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first)
1510 << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n";
1511 }
1512#endif
1513 }
1514 }
1515 }
1516 }
1517 }
1518 mySwitchedGreenFlanks.clear();
1519 }
1520}
1521
1522void
1524 for (LinkInfo& li : myLinkInfos) {
1525 for (auto it = li.myDriveways.begin(); it != li.myDriveways.end(); it++) {
1526 const DriveWay& dw = *it;
1527 if (dw.myNumericalID == numericalID) {
1528#ifdef DEBUG_DRIVEWAY_UPDATE
1529 std::cout << SIMTIME << " rail signal junction '" << getID() << "' requires update for driveway " << numericalID << "\n";
1530#endif
1531 std::vector<const MSEdge*> route = dw.myRoute;
1532 li.myDriveways.erase(it);
1533 if (li.myDriveways.size() == 0) {
1534 // rebuild default driveway
1535 li.myDriveways.push_back(li.buildDriveWay(route.begin(), route.end()));
1536 }
1537 return;
1538 }
1539 }
1540 }
1541}
1542
1543std::string
1545 MSRailSignal* rs = const_cast<MSRailSignal*>(this);
1546 if (myLinkInfos.size() == 1) {
1547 return toString(rs->getBlockingVehicles(0));
1548 } else {
1549 std::string result;
1550 for (int i = 0; i < (int)myLinkInfos.size(); i++) {
1551 result += toString(i) + ": " + toString(rs->getBlockingVehicles(i)) + ";";
1552 }
1553 return result;
1554 }
1555}
1556std::string
1558 MSRailSignal* rs = const_cast<MSRailSignal*>(this);
1559 if (myLinkInfos.size() == 1) {
1560 return toString(rs->getRivalVehicles(0));
1561 } else {
1562 std::string result;
1563 for (int i = 0; i < (int)myLinkInfos.size(); i++) {
1564 result += toString(i) + ": " + toString(rs->getRivalVehicles(i)) + ";";
1565 }
1566 return result;
1567 }
1568}
1569std::string
1571 MSRailSignal* rs = const_cast<MSRailSignal*>(this);
1572 if (myLinkInfos.size() == 1) {
1573 return toString(rs->getPriorityVehicles(0));
1574 } else {
1575 std::string result;
1576 for (int i = 0; i < (int)myLinkInfos.size(); i++) {
1577 result += toString(i) + ": " + toString(rs->getPriorityVehicles(i)) + ";";
1578 }
1579 return result;
1580 }
1581}
1582std::string
1584 MSRailSignal* rs = const_cast<MSRailSignal*>(this);
1585 if (myLinkInfos.size() == 1) {
1586 return rs->getConstraintInfo(0);
1587 } else {
1588 std::string result;
1589 for (int i = 0; i < (int)myLinkInfos.size(); i++) {
1590 result += toString(i) + ": " + rs->getConstraintInfo(i);
1591 }
1592 return result;
1593 }
1594}
1595
1596void
1597MSRailSignal::setParameter(const std::string& key, const std::string& value) {
1598 // some pre-defined parameters can be updated at runtime
1599 if (key == "moving-block") {
1600 bool movingBlock = StringUtils::toBool(value);
1601 if (movingBlock != myMovingBlock) {
1602 // recompute driveways
1603 myMovingBlock = movingBlock;
1604 for (LinkInfo& li : myLinkInfos) {
1605 li.reset();
1606 }
1608 setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
1609 }
1610 }
1611 Parameterised::setParameter(key, value);
1612}
1613
1614/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
std::vector< const MSEdge * > ConstMSEdgeVector
Definition: MSEdge.h:74
std::vector< MSEdge * > MSEdgeVector
Definition: MSEdge.h:73
#define DEBUG_COND_LINKINFO
#define DEBUG_HELPER(obj)
#define MAX_SIGNAL_WARNINGS
#define DEBUG_COND
#define MAX_BLOCK_LENGTH
ConstMSEdgeVector::const_iterator MSRouteIterator
Definition: MSRoute.h:54
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:266
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define SPEED2DIST(x)
Definition: SUMOTime.h:44
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define SIMTIME
Definition: SUMOTime.h:61
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
TrafficLightType
@ TURN
The link is a 180 degree turn.
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_LANES
@ SUMO_ATTR_TO
@ SUMO_ATTR_FROM
@ SUMO_ATTR_ID
@ SUMO_ATTR_TLLINKINDEX
link: the index of the link within the traffic light
bool gDebugFlag4
Definition: StdDefs.cpp:36
T MAX2(T a, T b)
Definition: StdDefs.h:77
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
Definition: StdDefs.h:41
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:282
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
const SUMOVehicleParameter & getParameter() const
Returns the vehicle's parameter (including departure definition)
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
const MSRoute & getRoute() const
Returns the current route.
A device that performs vehicle rerouting based on current edge speeds.
SUMOTime getPeriod() const
bool mayRerouteRailSignal() const
return whether the equipped vehicle may receive dispatch information at a rail signal
A road/street connecting two junctions.
Definition: MSEdge.h:77
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition: MSEdge.h:279
bool isNormal() const
return whether this edge is an internal edge
Definition: MSEdge.h:260
const MSJunction * getToJunction() const
Definition: MSEdge.h:415
double getLength() const
return the length of the edge
Definition: MSEdge.h:658
const MSJunction * getFromJunction() const
Definition: MSEdge.h:411
static bool gUseMesoSim
Definition: MSGlobals.h:103
The base class for an intersection.
Definition: MSJunction.h:58
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:130
virtual const MSJunctionLogic * getLogic() const
Definition: MSJunction.h:138
const ConstMSEdgeVector & getIncoming() const
Definition: MSJunction.h:105
virtual const MSLogicJunction::LinkBits & getFoesFor(int linkIndex) const
Returns the foes for the given link.
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
Definition: MSLane.cpp:2365
const MSEdge * getNextNormal() const
Returns the lane's follower if it is an internal lane, the edge of the lane otherwise.
Definition: MSLane.cpp:2175
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:879
double getLength() const
Returns the lane's length.
Definition: MSLane.h:575
bool isInternal() const
Definition: MSLane.cpp:2330
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
Definition: MSLane.cpp:4252
bool isEmpty() const
Definition: MSLane.h:814
MSEdge & getEdge() const
Returns the lane's edge.
Definition: MSLane.h:713
const std::vector< MSLink * > & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.h:675
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:321
The definition of a single phase of a tls logic.
const std::string & getState() const
Returns the state within this phase.
void setState(const std::string &_state)
A base class for constraints.
virtual std::string getDescription() const
ConstraintType getType() const
virtual bool cleared() const =0
whether the constraint has been met
void addSignal(MSRailSignal *signal)
static MSRailSignalControl & getInstance()
const std::set< const MSEdge * > & getUsedEdges() const
void registerProtectedDriveway(MSRailSignal *rs, int driveWayID, const MSEdge *protectedBidi)
mark driveway that must receive additional checks if protectedBidi is ever used by a train route
A signal for rails.
Definition: MSRailSignal.h:46
bool constraintsAllow(const SUMOVehicle *veh) const
whether the given vehicle is free to drive
static VehicleVector myRivalVehicles
Definition: MSRailSignal.h:486
std::string getBlockingVehicleIDs() const
Phases myPhases
The list of phases this logic uses.
Definition: MSRailSignal.h:457
std::string getConstraintInfo(int linkIndex)
return information regarding active rail signal constraints for the closest approaching vehicle
static VehicleVector myPriorityVehicles
Definition: MSRailSignal.h:487
int myPhaseIndex
MSTrafficLightLogic requires that the phase index changes whenever signals change their state.
Definition: MSRailSignal.h:463
SUMOTime getOffsetFromIndex(int index) const override
Returns the position (start of a phase during a cycle) from of a given step.
void setParameter(const std::string &key, const std::string &value) override
Sets a parameter and updates internal constants.
static std::string myConstraintInfo
Definition: MSRailSignal.h:488
MSPhaseDefinition myCurrentPhase
The current phase.
Definition: MSRailSignal.h:460
void addConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
register contraint for signal switching
static std::string getClickableTLLinkID(MSLink *link)
return logicID_linkIndex in a way that allows clicking in sumo-gui
std::vector< LinkInfo > myLinkInfos
data storage for every link at this node (more than one when directly guarding a switch)
Definition: MSRailSignal.h:424
SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const override
Returns the index of the logic at the given simulation step.
std::string getPriorityVehicleIDs() const
MSRailSignal(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, SUMOTime delay, const Parameterised::Map &parameters)
Constructor.
static void appendMapIndex(LaneVisitedMap &map, const MSLane *lane)
append to map by map index and avoid undefined behavior
VehicleVector getBlockingVehicles(int linkIndex) override
return vehicles that block the intersection/rail signal for vehicles that wish to pass the given link...
VehicleVector getRivalVehicles(int linkIndex) override
return vehicles that approach the intersection/rail signal and are in conflict with vehicles that wis...
static int myDriveWayIndex
Definition: MSRailSignal.h:476
static std::string describeLinks(std::vector< MSLink * > links)
print link descriptions
void writeBlocks(OutputDevice &od) const
write rail signal block output for all links and driveways
~MSRailSignal()
Destructor.
void adaptLinkInformationFrom(const MSTrafficLightLogic &logic) override
Applies information about controlled links and lanes from the given logic.
static VehicleVector myBlockingVehicles
Definition: MSRailSignal.h:485
void removeConstraints()
void storeTraCIVehicles(int linkIndex)
update vehicle lists for traci calls
int getIndexFromOffset(SUMOTime offset) const override
Returns the step (the phasenumber) of a given position of the cycle.
static Approaching getClosest(MSLink *link)
get the closest vehicle approaching the given link
void init(NLDetectorBuilder &nb) override
Initialises the rail signal with information about adjacent rail signals.
std::map< std::string, std::vector< MSRailSignalConstraint * > > myConstraints
map from tripId to constraint list
Definition: MSRailSignal.h:469
static std::map< std::pair< int, int >, bool > myDriveWayCompatibility
Definition: MSRailSignal.h:475
std::pair< const SUMOVehicle *const, const MSLink::ApproachingVehicleInformation > Approaching
Definition: MSRailSignal.h:261
int getPhaseNumber() const override
Returns the number of phases.
const MSPhaseDefinition & getPhase(int givenstep) const override
Returns the definition of the phase from the given position within the plan.
static void recheckGreen()
final check for driveway compatibility of signals that switched green in this step
static std::string getJunctionLinkID(MSLink *link)
return junctionID_junctionLinkIndex
static int myNumWarnings
Definition: MSRailSignal.h:471
SUMOTime trySwitch() override
Switches to the next phase.
const DriveWay & retrieveDriveWay(int numericalID) const
static bool myStoreVehicles
Definition: MSRailSignal.h:484
std::map< const MSLane *, int, ComparatorNumericalIdLess > LaneVisitedMap
Definition: MSRailSignal.h:263
bool myMovingBlock
whether the signal is in moving block mode (only protects from oncoming and flanking trains)
Definition: MSRailSignal.h:466
bool removeConstraint(const std::string &tripId, MSRailSignalConstraint *constraint)
remove contraint for signal switching
static bool hasOncomingRailTraffic(MSLink *link, const MSVehicle *ego, bool &brakeBeforeSignal)
static std::vector< std::pair< MSLink *, int > > mySwitchedGreenFlanks
list of signals that switched green along with driveway index
Definition: MSRailSignal.h:474
const Phases & getPhases() const override
Returns the phases of this tls program.
const MSPhaseDefinition & getCurrentPhaseDef() const override
Returns the definition of the current phase.
void updateDriveway(int numericalID)
update driveway for extended deadlock protection
std::string getConstraintInfo() const
static std::string formatVisitedMap(const LaneVisitedMap &visited)
print link descriptions
void updateCurrentPhase()
returns the state of the signal that actually required
void addLink(MSLink *link, MSLane *lane, int pos) override
Adds a link on building.
std::string getRivalVehicleIDs() const
static bool hasInsertionConstraint(MSLink *link, const MSVehicle *veh, std::string &info, bool &isInsertionOrder)
VehicleVector getPriorityVehicles(int linkIndex) override
return vehicles that approach the intersection/rail signal and have priority over vehicles that wish ...
static std::string getTLLinkID(MSLink *link)
return logicID_linkIndex
int getCurrentPhaseIndex() const override
Returns the current index within the program.
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
MSRouteIterator end() const
Returns the end of the list of edges to pass.
Definition: MSRoute.cpp:80
MSRouteIterator begin() const
Returns the begin of the list of edges to pass.
Definition: MSRoute.cpp:74
static void reroute(SUMOVehicle &vehicle, const SUMOTime currentTime, const std::string &info, const bool onInit=false, const bool silent=false, const MSEdgeVector &prohibited=MSEdgeVector())
initiate the rerouting, create router / thread pool on first use
A class that stores and controls tls and switching of their programs.
The parent class for traffic light logics.
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
std::vector< const SUMOVehicle * > VehicleVector
list of vehicles
SUMOTime myDefaultCycleTime
The cycle time (without changes)
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index.
int myNumLinks
number of controlled links
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
virtual void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index.
Representation of a vehicle in the micro simulation.
Definition: MSVehicle.h:77
Builds detectors for microsim.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
void lf()
writes a line feed if applicable
Definition: OutputDevice.h:239
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:251
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
std::map< std::string, std::string > Map
parameters map
Definition: Parameterised.h:45
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
virtual double getSpeed() const =0
Returns the object's current speed.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual int getRoutePosition() const =0
return index of edge within route
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
virtual const MSRoute & getRoute() const =0
Returns the current route.
Definition of vehicle stop (position and duration)
std::string join
the id of the vehicle (train portion) to which this vehicle shall be joined
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
Definition: json.hpp:4471
void checkFlanks(const std::vector< MSLane * > &lanes, const LaneVisitedMap &visited, bool allFoes)
find switches that threaten this driveway
void writeBlocks(OutputDevice &od) const
Write block items for this driveway.
void buildRoute(MSLink *origin, double length, MSRouteIterator next, MSRouteIterator end, LaneVisitedMap &visited)
std::vector< MSLink * > myFlankSwitches
Definition: MSRailSignal.h:323
int myCoreSize
number of edges in myRoute where overlap with other driveways is forbidden
Definition: MSRailSignal.h:299
bool deadlockLaneOccupied(bool store=true) const
whether any of myBidiExtended is occupied by a vehicle that targets myBidi
const MSEdge * myProtectedBidi
switch assumed safe from bidi-traffic
Definition: MSRailSignal.h:293
std::vector< MSLink * > myProtectingSwitchesBidi
subset of myProtectingSwitches that protects from oncoming trains
Definition: MSRailSignal.h:331
std::vector< const MSLane * > myConflictLanes
the lanes that must be clear of trains before this signal can switch to green
Definition: MSRailSignal.h:319
bool overlap(const DriveWay &other) const
Wether this driveway (route) overlaps with the given one.
int myNumericalID
global driveway index
Definition: MSRailSignal.h:284
std::vector< MSLink * > myConflictLinks
Definition: MSRailSignal.h:336
void checkCrossingFlanks(MSLink *dwLink, const LaneVisitedMap &visited)
find links that cross the driveway without entering it
std::vector< MSLane * > myBidi
Definition: MSRailSignal.h:308
void findFlankProtection(MSLink *link, double length, LaneVisitedMap &visited, MSLink *origLink)
find upstream protection from the given link
bool conflictLaneOccupied(const std::string &joinVehicle="", bool store=true) const
whether any of myConflictLanes is occupied (vehicles that are the target of a join must be ignored)
std::vector< const MSLane * > myFlank
Definition: MSRailSignal.h:316
std::vector< const MSEdge * > myRoute
list of edges for matching against train routes
Definition: MSRailSignal.h:296
bool hasLinkConflict(const Approaching &closest, MSLink *foeLink) const
Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link...
bool findProtection(const Approaching &veh, MSLink *link) const
find protection for the given vehicle starting at a switch
std::vector< MSLink * > myProtectingSwitches
Definition: MSRailSignal.h:329
std::vector< MSLane * > myForward
Definition: MSRailSignal.h:303
bool conflictLinkApproached() const
Whether any of the conflict links have approaching vehicles.
bool reserve(const Approaching &closest, MSEdgeVector &occupied)
attempt reserve this driveway for the given vehicle
bool flankConflict(const DriveWay &other) const
Wether there is a flank conflict with the given driveway.
static bool mustYield(const Approaching &veh, const Approaching &foe)
Whether veh must yield to the foe train.