 |
Eclipse SUMO - Simulation of Urban MObility
|
Go to the documentation of this file.
51 #define MAX_BLOCK_LENGTH 20000
52 #define MAX_SIGNAL_WARNINGS 10
57 #define DEBUG_SIGNALSTATE
58 #define DEBUG_SIGNALSTATE_PRIORITY
59 #define DEBUG_FIND_PROTECTION
62 #define DEBUG_COND DEBUG_HELPER(this)
63 #define DEBUG_COND_LINKINFO DEBUG_HELPER(myLink->getTLLogic())
64 #define DEBUG_HELPER(obj) ((obj)->isSelected())
77 const std::string&
id,
const std::string& programID,
78 const std::map<std::string, std::string>& parameters) :
89 if (links.size() != 1) {
91 +
" links controlled by index " +
toString(links[0]->getTLIndex()));
123 #ifdef DEBUG_SIGNALSTATE
127 std::string state(
myLinks.size(),
'G');
129 if (li.myLink->getApproaching().size() > 0) {
131 DriveWay& driveway = li.getDriveWay(closest.first);
135 if (!driveway.
reserve(closest, occupied)) {
136 state[li.myLink->getTLIndex()] =
'r';
137 if (occupied.size() > 0) {
138 li.reroute(const_cast<SUMOVehicle*>(closest.first), occupied);
140 #ifdef DEBUG_SIGNALSTATE
142 std::cout <<
SIMTIME <<
" rsl=" << li.getID() <<
" veh=" << closest.first->getID() <<
" notReserved\n";
146 state[li.myLink->getTLIndex()] =
'G';
147 #ifdef DEBUG_SIGNALSTATE
149 std::cout <<
SIMTIME <<
" rsl=" << li.getID() <<
" veh=" << closest.first->getID() <<
" reserved\n";
154 DriveWay& driveway = li.myDriveways.front();
156 #ifdef DEBUG_SIGNALSTATE
158 std::cout <<
SIMTIME <<
" rsl=" << li.getID() <<
" red for default driveway\n";
161 state[li.myLink->getTLIndex()] =
'r';
169 #ifdef DEBUG_SIGNALSTATE
240 for (
MSLink* link : links) {
241 result += link->getDescription() +
" ";
249 double minDist = std::numeric_limits<double>::max();
252 if (apprIt->second.dist < minDist) {
253 minDist = apprIt->second.
dist;
283 for (
const DriveWay& dw : li.myDriveways) {
296 if (bidi ==
nullptr) {
337 myLink(link), myUniqueDriveWay(false),
338 myLastRerouteTime(-1),
339 myLastRerouteVehicle(nullptr) {
348 return myLink->getTLLogic()->getID() +
"_" +
toString(myLink->getTLIndex());
354 if (myUniqueDriveWay) {
355 return myDriveways.front();
357 MSEdge* first = &myLink->getLane()->getEdge();
360 WRITE_WARNING(
"Invalid approach information after rerouting");
361 return myDriveways.front();
366 auto itRoute = firstIt;
367 auto itDwRoute = dw.myRoute.begin();
369 while (itRoute != veh->
getRoute().
end() && itDwRoute != dw.myRoute.end()) {
370 if (*itRoute != *itDwRoute) {
383 return buildDriveWay(firstIt, veh->
getRoute().
end());
412 DriveWay dw((
int)myDriveways.size());
414 std::vector<MSLane*> before;
415 visited.insert(myLink->getLaneBefore());
417 if (fromBidi !=
nullptr) {
419 visited.insert(fromBidi);
420 before.push_back(fromBidi);
422 dw.buildRoute(myLink, 0., first, end, visited);
423 dw.checkFlanks(dw.myForward, visited,
true);
424 dw.checkFlanks(dw.myBidi, visited,
false);
425 dw.checkFlanks(before, visited,
true);
427 for (
MSLink* link : dw.myFlankSwitches) {
429 dw.findFlankProtection(link, 0, visited, link);
432 #ifdef DEBUG_BUILD_DRIVEWAY
434 std::cout <<
" buildDriveWay railSignal=" <<
getID() <<
" dw=" << dw.myIndex
435 <<
"\n route=" <<
toString(dw.myRoute)
436 <<
"\n forward=" <<
toString(dw.myForward)
437 <<
"\n bidi=" <<
toString(dw.myBidi)
438 <<
"\n protSwitch=" <<
describeLinks(dw.myProtectingSwitches)
443 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myForward.begin(), dw.myForward.end());
444 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myBidi.begin(), dw.myBidi.end());
445 dw.myConflictLanes.insert(dw.myConflictLanes.end(), dw.myFlank.begin(), dw.myFlank.end());
447 myDriveways.push_back(dw);
448 return myDriveways.back();
456 if (rDev !=
nullptr &&
457 (myLastRerouteVehicle != veh
461 myLastRerouteVehicle = veh;
462 myLastRerouteTime = now;
468 std::cout <<
SIMTIME <<
" reroute veh=" << veh->
getID() <<
" rs=" <<
getID() <<
" occupied=" <<
toString(occupied) <<
"\n";
472 veh->
reroute(now,
"railSignal:" +
getID(), router,
false,
false,
true);
476 std::cout <<
" rerouting successful\n";
483 std::cout <<
" rerouting failed: " << error.what() <<
"\n";
499 if (conflictLaneOccupied()) {
500 for (
MSLane* bidi : myBidi) {
501 if (!bidi->empty() && bidi->getBidiLane() !=
nullptr) {
502 occupied.push_back(&bidi->getBidiLane()->getEdge());
505 #ifdef DEBUG_SIGNALSTATE
507 std::cout <<
" conflictLaneOccupied\n";
512 for (
MSLink* link : myProtectingSwitches) {
513 if (!findProtection(closest, link)) {
514 #ifdef DEBUG_SIGNALSTATE
516 std::cout <<
" no protection at switch " << link->getDescription() <<
"\n";
522 for (
MSLink* foeLink : myConflictLinks) {
523 if (hasLinkConflict(closest, foeLink)) {
524 #ifdef DEBUG_SIGNALSTATE
526 std::cout <<
" linkConflict with " <<
getTLLinkID(foeLink) <<
"\n";
532 myActive = closest.first;
539 for (
MSLink* foeLink : myConflictLinks) {
540 if (foeLink->getApproaching().size() > 0) {
550 #ifdef DEBUG_SIGNALSTATE_PRIORITY
552 std::cout <<
" checkLinkConflict foeLink=" <<
getTLLinkID(foeLink) <<
"\n";
557 #ifdef DEBUG_SIGNALSTATE_PRIORITY
559 std::cout <<
" approaching foe=" << foe.first->getID() <<
"\n";
563 assert(foeTLL !=
nullptr);
564 const MSRailSignal* constFoeRS = dynamic_cast<const MSRailSignal*>(foeTLL);
565 MSRailSignal* foeRS = const_cast<MSRailSignal*>(constFoeRS);
566 if (foeRS !=
nullptr) {
569 !overlap(foeDriveWay)) {
570 #ifdef DEBUG_SIGNALSTATE_PRIORITY
573 std::cout <<
" foe blocked\n";
575 std::cout <<
" no overlap\n";
581 #ifdef DEBUG_SIGNALSTATE_PRIORITY
584 <<
" aSB=" << veh.second.arrivalSpeedBraking <<
" foeASB=" << foe.second.arrivalSpeedBraking
585 <<
" aT=" << veh.second.arrivalTime <<
" foeAT=" << foe.second.arrivalTime
586 <<
" aS=" << veh.first->getSpeed() <<
" foeS=" << foe.first->getSpeed()
587 <<
" aD=" << veh.second.dist <<
" foeD=" << foe.second.dist
591 if (foe.second.arrivalSpeedBraking == veh.second.arrivalSpeedBraking) {
592 if (foe.second.arrivalTime == veh.second.arrivalTime) {
593 if (foe.first->getSpeed() == veh.first->getSpeed()) {
594 if (foe.second.dist == veh.second.dist) {
595 return foe.first->getNumericalID() < veh.first->getNumericalID();
597 return foe.second.dist < veh.second.dist;
600 return foe.first->getSpeed() > veh.first->getSpeed();
603 return foe.second.arrivalTime < veh.second.arrivalTime;
606 return foe.second.arrivalSpeedBraking > veh.second.arrivalSpeedBraking;
616 for (
const MSLane* lane : myConflictLanes) {
617 if (!lane->isEmpty()) {
618 #ifdef DEBUG_SIGNALSTATE
620 std::cout <<
SIMTIME <<
" conflictLane " << lane->getID() <<
" occupied\n";
632 double flankApproachingDist = std::numeric_limits<double>::max();
635 flankApproachingDist = closest.second.dist;
637 #ifdef DEBUG_FIND_PROTECTION
639 std::cout <<
SIMTIME <<
" findProtection for link=" << link->
getDescription() <<
" flankApproachingDist=" << flankApproachingDist <<
"\n";
643 if (l2->getLane() != link->
getLane()) {
644 #ifdef DEBUG_FIND_PROTECTION
646 std::cout <<
" protectionCandidate=" << l2->getDescription() <<
" l2Via=" <<
Named::getIDSecure(l2->getViaLane()) <<
" occupied=" << !l2->getViaLane()->isEmpty() <<
"\n";
649 if (l2->getViaLane() !=
nullptr && !l2->getViaLane()->isEmpty()) {
650 #ifdef DEBUG_FIND_PROTECTION
652 std::cout <<
" protection from internal=" << l2->getViaLane()->getID() <<
"\n";
657 if (l2->getApproaching().size() > 0) {
659 if (closest2.second.dist < flankApproachingDist) {
660 #ifdef DEBUG_FIND_PROTECTION
662 std::cout <<
" protection from veh=" << closest2.first->getID() <<
"\n";
686 return tmp.
reserve(veh, occupied);
693 for (
const MSEdge* edge : myRoute) {
719 std::vector<std::string> signals;
720 for (
MSLink* link : myConflictLinks) {
733 bool seekForwardSignal =
true;
734 bool seekBidiSwitch =
true;
737 while ((seekForwardSignal || seekBidiSwitch)) {
741 " exceeds maximum length (stopped searching after edge '" + toLane->
getEdge().
getID() +
"' (length=" +
toString(length) +
"m).");
748 if (visited.count(toLane) != 0) {
753 myRoute.push_back(&toLane->
getEdge());
758 visited.insert(toLane);
761 if (seekForwardSignal) {
762 myForward.push_back(toLane);
763 }
else if (bidi ==
nullptr) {
764 seekBidiSwitch =
false;
766 if (bidi !=
nullptr) {
767 myBidi.push_back(bidi);
768 visited.insert(bidi);
769 if (!seekForwardSignal) {
775 for (
MSLink* link : ili.lane->getLinkCont()) {
779 if (link->getViaLaneOrLane() != bidi) {
781 myProtectingSwitches.push_back(ili.viaLink);
790 for (
MSLink* link : links) {
791 if (((next != end && &link->getLane()->getEdge() == *next) ||
793 &&
isRailway(link->getViaLaneOrLane()->getPermissions())) {
794 toLane = link->getViaLaneOrLane();
795 if (link->getTLLogic() !=
nullptr) {
796 if (link->getTLLogic() == origin->
getTLLogic()) {
800 seekForwardSignal =
false;
801 seekBidiSwitch = bidi !=
nullptr;
806 if (toLane ==
nullptr) {
809 toLane = (*next)->getLanes()[0];
820 #ifdef DEBUG_CHECK_FLANKS
821 std::cout <<
" checkFlanks lanes=" <<
toString(lanes) <<
"\n visited=" <<
joinNamedToString(visited,
" ") <<
" allFoes=" << allFoes <<
"\n";
823 for (
MSLane* lane : lanes) {
824 if (lane->isInternal()) {
827 for (
auto ili : lane->getIncomingLanes()) {
828 if (visited.count(ili.lane->getNormalPredecessorLane()) == 0) {
829 #ifdef DEBUG_CHECK_FLANKS
830 std::cout <<
" add flankSwitch junction=" << ili.viaLink->getJunction()->getID() <<
" index=" << ili.viaLink->getIndex() <<
"\n";
832 myFlankSwitches.push_back(ili.viaLink);
833 }
else if (allFoes) {
835 checkCrossingFlanks(ili.viaLink, visited);
844 #ifdef DEBUG_CHECK_FLANKS
849 assert(logic !=
nullptr);
851 if (in->isInternal()) {
854 for (
MSLane* inLane : in->getLanes()) {
855 if (
isRailway(inLane->getPermissions()) && visited.count(inLane) == 0) {
856 for (
MSLink* link : inLane->getLinkCont()) {
857 if (link->getIndex() >= 0 && logic->
getFoesFor(dwLink->
getIndex()).test(link->getIndex())
858 && visited.count(link->getLane()) == 0) {
859 #ifdef DEBUG_CHECK_FLANKS
860 std::cout <<
" add crossing flankSwitch junction=" << junction->
getID() <<
" index=" << link->getIndex() <<
"\n";
862 if (link->getViaLane() ==
nullptr) {
863 myFlankSwitches.push_back(link);
865 myFlankSwitches.push_back(link->getViaLane()->getLinkCont().front());
876 #ifdef DEBUG_CHECK_FLANKS
877 std::cout <<
" findFlankProtection link=" << link->
getDescription() <<
" length=" << length <<
" origLink=" << origLink->
getDescription() <<
"\n";
881 myConflictLinks.push_back(link);
891 if (visited.count(lane) == 0) {
892 visited.insert(lane);
895 myFlank.push_back(lane);
896 findFlankProtection(lane->
getIncomingLanes().front().viaLink, length, visited, origLink);
898 bool foundPSwitch =
false;
900 #ifdef DEBUG_CHECK_FLANKS
901 std::cout <<
" lane=" << lane->
getID() <<
" cand=" << l2->getDescription() <<
"\n";
906 #ifdef DEBUG_CHECK_FLANKS
907 std::cout <<
" protectingSwitch=" << l2->getDescription() <<
" for flank=" << link->
getDescription() <<
"\n";
909 myProtectingSwitches.push_back(link);
913 myFlank.push_back(lane);
917 findFlankProtection(ili.viaLink, length, visited, origLink);
924 myMaxFlankLength =
MAX2(myMaxFlankLength, length);
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
#define UNUSED_PARAMETER(x)
std::vector< const MSLane * > myConflictLanes
the lanes that must be clear of trains before this signal can switch to green
#define MAX_SIGNAL_WARNINGS
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index.
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index.
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
LinkState getState() const
Returns the current state of the link.
SUMOTime getOffsetFromIndex(int index) const
Returns the position (start of a phase during a cycle) from of a given step.
int getIndexFromOffset(SUMOTime offset) const
Returns the step (the phasenumber) of a given position of the cycle.
A device that performs vehicle rerouting based on current edge speeds.
#define WRITE_WARNING(msg)
Representation of a lane in the micro simulation.
SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const
Returns the index of the logic at the given simulation step.
SUMOTime trySwitch()
Switches to the next phase.
SUMOTime getPeriod() const
The base class for an intersection.
Static storage of an output device and its base (abstract) implementation.
MSRouteIterator end() const
Returns the end of the list of edges to pass.
std::vector< MSLink * > myProtectingSwitches
ConstMSEdgeVector::const_iterator MSRouteIterator
void buildRoute(MSLink *origin, double length, MSRouteIterator next, MSRouteIterator end, LaneSet &visited)
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
virtual const std::string & getID() const =0
Get the vehicle's ID.
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
bool hasLinkConflict(const Approaching &closest, MSLink *foeLink) const
Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link...
ApproachingVehicleInformation getApproaching(const SUMOVehicle *veh) const
LinkInfo(MSLink *link)
constructor
int myPhaseIndex
MSTrafficLightLogic requires that the phase index changes whenever signals change their state.
std::vector< MSLane * > myBidi
Representation of a vehicle.
const MSRoute & getRoute() const
Returns the current route.
std::vector< const MSEdge * > ConstMSEdgeVector
void init(NLDetectorBuilder &nb)
Initialises the rail signal with information about adjacent rail signals.
int getPhaseNumber() const
Returns the number of phases.
const ConstMSEdgeVector & getEdges() const
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
const Phases & getPhases() const
Returns the phases of this tls program.
bool overlap(const DriveWay &other) const
Wether this driveway overlaps with the given one.
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
static std::string getTLLinkID(MSLink *link)
return logicID_linkIndex
int getIndex() const
Returns the respond index (for visualization)
void findFlankProtection(MSLink *link, double length, LaneSet &visited, MSLink *origLink)
find upstream protection from the given link
std::vector< const MSLane * > myFlank
bool isNormal() const
return whether this edge is an internal edge
virtual void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
const ConstMSEdgeVector & getIncoming() const
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
void setState(const std::string &_state)
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
std::set< const MSLane *, ComparatorNumericalIdLess > LaneSet
void checkCrossingFlanks(MSLink *dwLink, const LaneSet &visited)
find links that cross the driveway without entering it
std::string getDescription() const
get string description for this link
void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
std::vector< DriveWay > myDriveways
all driveways immediately following this link
The link is a 180 degree turn.
virtual const MSRoute & getRoute() const =0
Returns the current route.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
bool conflictLinkApproached() const
Whether any of the conflict linkes have approaching vehicles.
static Approaching getClosest(MSLink *link)
get the closest vehicle approaching the given link
const MSJunction * getFromJunction() const
static std::string getClickableTLLinkID(MSLink *link)
return logicID_linkIndex in a way that allows clicking in sumo-gui
DriveWay & getDriveWay(const SUMOVehicle *)
retrieve an existing Driveway or construct a new driveway based on the vehicles route
MSLane * getLane() const
Returns the connected lane.
int getCurrentPhaseIndex() const
Returns the current index within the program.
MSRailSignal(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const std::map< std::string, std::string > ¶meters)
Constructor.
static std::string describeLinks(std::vector< MSLink * > links)
print link descriptions
const std::string & getState() const
Returns the state within this phase.
std::pair< const SUMOVehicle *const, const MSLink::ApproachingVehicleInformation > Approaching
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
MSJunction * getJunction() const
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
double getLength() const
Returns the lane's length.
void checkFlanks(const std::vector< MSLane * > &lanes, const LaneSet &visited, bool allFoes)
find switches that threathen this driveway
bool findProtection(const Approaching &veh, MSLink *link) const
find protection for the given vehicle starting at a switch
void writeBlocks(OutputDevice &od) const
write rail signal block output for all links and driveways
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
MSPhaseDefinition myCurrentPhase
The current phase.
virtual const MSJunctionLogic * getLogic() const
void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
std::vector< const MSEdge * > myRoute
list of lanes for matching against train routes
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
A road/street connecting two junctions.
~MSRailSignal()
Destructor.
SumoXMLNodeType getType() const
return the type of this Junction
The parent class for traffic light logics.
std::string getID() const
return id for this railsignal-link
const MSJunction * getToJunction() const
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
void reroute(SUMOVehicle *veh, const MSEdgeVector &occupied)
try rerouting vehicle if reservation failed
MSEdge & getEdge() const
Returns the lane's edge.
Phases myPhases
The list of phases this logic uses.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
virtual void reroute(SUMOTime t, const std::string &info, SUMOAbstractRouter< MSEdge, SUMOVehicle > &router, const bool onInit=false, const bool withTaz=false, const bool silent=false)=0
Performs a rerouting using the given router.
link: the index of the link within the traffic light
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
std::vector< MSEdge * > MSEdgeVector
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
bool conflictLaneOccupied() const
whether any of myConflictLanes is occupied
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
static bool hasOncomingRailTraffic(MSLink *link)
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
SUMOTime myDefaultCycleTime
The cycle time (without changes)
void updateCurrentPhase()
returns the state of the signal that actually required
#define DEBUG_COND_LINKINFO
A class that stores and controls tls and switching of their programs.
bool reserve(const Approaching &closest, MSEdgeVector &occupied)
attempt reserve this driveway for the given vehicle
The link has red light (must brake)
std::vector< LinkInfo > myLinkInfos
data storage for every link at this node (more than one when directly guarding a switch)
const MSLane * getLaneBefore() const
return the internalLaneBefore if it exists and the laneBefore otherwise
The definition of a single phase of a tls logic.
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
int getTLIndex() const
Returns the TLS index.
const std::string & getID() const
Returns the id.
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
void writeBlocks(OutputDevice &od) const
Write block items for this driveway.
const MSPhaseDefinition & getPhase(int givenstep) const
Returns the definition of the phase from the given position within the plan.
Builds detectors for microsim.
virtual const MSLogicJunction::LinkBits & getFoesFor(int linkIndex) const
Returns the foes for the given link.
std::vector< MSLink * > myConflictLinks
const MSTrafficLightLogic * getTLLogic() const
Returns the TLS index.
Representation of a vehicle in the micro simulation.
DriveWay & buildDriveWay(MSRouteIterator first, MSRouteIterator end)
construct a new driveway by searching along the given route until all block structures are found