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) {
360 WRITE_WARNING(
"Invalid approach information after rerouting");
366 auto itRoute = firstIt;
367 auto itDwRoute = dw.myRoute.begin();
369 while (itRoute != veh->
getRoute().
end() && itDwRoute != dw.myRoute.end()) {
370 if (*itRoute != *itDwRoute) {
414 std::vector<MSLane*> before;
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());
456 if (rDev !=
nullptr &&
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);
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);
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
const std::string & getState() const
Returns the state within this phase.
Builds detectors for microsim.
void writeBlocks(OutputDevice &od) const
write rail signal block output for all links and driveways
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.
MSEdge & getEdge() const
Returns the lane's edge.
Representation of a vehicle in the micro simulation.
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
std::vector< const MSLane * > myConflictLanes
the lanes that must be clear of trains before this signal can switch to green
const ConstMSEdgeVector & getEdges() const
static bool hasOncomingRailTraffic(MSLink *link)
MSLane * getLane() const
Returns the connected lane.
void updateCurrentPhase()
returns the state of the signal that actually required
virtual const std::string & getID() const =0
Get the vehicle's ID.
const MSPhaseDefinition & getPhase(int givenstep) const
Returns the definition of the phase from the given position within the plan.
virtual MSVehicleDevice * getDevice(const std::type_info &type) const =0
Returns a device of the given type if it exists or 0.
virtual const MSRoute & getRoute() const =0
Returns the current route.
static std::string getClickableTLLinkID(MSLink *link)
return logicID_linkIndex in a way that allows clicking in sumo-gui
std::vector< DriveWay > myDriveways
all driveways immediately following this link
SUMOTime myLastRerouteTime
The base class for an intersection.
const MSLane * getLaneBefore() const
return the internalLaneBefore if it exists and the laneBefore otherwise
The link is a 180 degree turn.
int getTLIndex() const
Returns the TLS index.
std::vector< MSLink * > myConflictLinks
A device that performs vehicle rerouting based on current edge speeds.
std::vector< LinkInfo > myLinkInfos
data storage for every link at this node (more than one when directly guarding a switch) ...
MSVehicle * getFirstAnyVehicle() const
returns the first vehicle that is fully or partially on this lane
void checkCrossingFlanks(MSLink *dwLink, const LaneSet &visited)
find links that cross the driveway without entering it
int getIndexFromOffset(SUMOTime offset) const
Returns the step (the phasenumber) of a given position of the cycle.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
bool conflictLinkApproached() const
Whether any of the conflict linkes have approaching vehicles.
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
double getLength() const
Returns the lane's length.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const MSRoute & getRoute() const
Returns the current route.
std::vector< MSLane * > myBidi
std::vector< MSLink * > myProtectingSwitches
std::vector< const MSEdge * > ConstMSEdgeVector
std::string getDescription() const
get string description for this link
const std::string & getID() const
Returns the id.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
#define DEBUG_COND_LINKINFO
static SUMOAbstractRouter< MSEdge, SUMOVehicle > & getRouterTT(const MSEdgeVector &prohibited=MSEdgeVector())
return the router instance
bool hasLinkConflict(const Approaching &closest, MSLink *foeLink) const
Whether the approaching vehicle is prevent from driving by another vehicle approaching the given link...
const MSJunction * getToJunction() const
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
#define UNUSED_PARAMETER(x)
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
#define WRITE_WARNING(msg)
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index...
LinkState getState() const
Returns the current state of the link.
A class that stores and controls tls and switching of their programs.
std::vector< const MSEdge * > myRoute
list of lanes for matching against train routes
A road/street connecting two junctions.
void reroute(SUMOVehicle *veh, const MSEdgeVector &occupied)
try rerouting vehicle if reservation failed
DriveWay & buildDriveWay(MSRouteIterator first, MSRouteIterator end)
construct a new driveway by searching along the given route until all block structures are found ...
void findFlankProtection(MSLink *link, double length, LaneSet &visited, MSLink *origLink)
find upstream protection from the given link
bool findProtection(const Approaching &veh, MSLink *link) const
find protection for the given vehicle starting at a switch
void setState(const std::string &_state)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
SUMOTime myDefaultCycleTime
The cycle time (without changes)
Representation of a vehicle.
void buildRoute(MSLink *origin, double length, MSRouteIterator next, MSRouteIterator end, LaneSet &visited)
const MSTrafficLightLogic * getTLLogic() const
Returns the TLS index.
void init(NLDetectorBuilder &nb)
Initialises the rail signal with information about adjacent rail signals.
ApproachingVehicleInformation getApproaching(const SUMOVehicle *veh) const
Phases myPhases
The list of phases this logic uses.
SUMOVehicle * myLastRerouteVehicle
ConstMSEdgeVector::const_iterator MSRouteIterator
const Phases & getPhases() const
Returns the phases of this tls program.
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
DriveWay & getDriveWay(const SUMOVehicle *)
retrieve an existing Driveway or construct a new driveway based on the vehicles route ...
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
virtual const MSLogicJunction::LinkBits & getFoesFor(int linkIndex) const
Returns the foes for the given link.
const ConstMSEdgeVector & getIncoming() const
static std::string describeLinks(std::vector< MSLink *> links)
print link descriptions
int getPhaseNumber() const
Returns the number of phases.
#define MAX_SIGNAL_WARNINGS
std::vector< const MSLane * > myFlank
SUMOTime trySwitch()
Switches to the next phase.
SUMOTime getPeriod() const
int myPhaseIndex
MSTrafficLightLogic requires that the phase index changes whenever signals change their state...
std::vector< MSLink * > LinkVector
Definition of the list of links that are subjected to this tls.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
LinkVectorVector myLinks
The list of LinkVectors; each vector contains the links that belong to the same link index...
MSRailSignal(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &programID, const std::map< std::string, std::string > ¶meters)
Constructor.
void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
std::set< const MSLane *, ComparatorNumericalIdLess > LaneSet
void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
bool reserve(const Approaching &closest, MSEdgeVector &occupied)
attempt reserve this driveway for the given vehicle
bool conflictLaneOccupied() const
whether any of myConflictLanes is occupied
static Approaching getClosest(MSLink *link)
get the closest vehicle approaching the given link
const MSJunction * getFromJunction() const
The link has red light (must brake)
MSJunction * getJunction() const
virtual void addLink(MSLink *link, MSLane *lane, int pos)
Adds a link on building.
void checkFlanks(const std::vector< MSLane *> &lanes, const LaneSet &visited, bool allFoes)
find switches that threathen this driveway
MSLane * getViaLaneOrLane() const
return the via lane if it exists and the lane otherwise
MSLane * getBidiLane() const
retrieve bidirectional lane or nullptr
int getIndex() const
Returns the respond index (for visualization)
std::pair< const SUMOVehicle *const, const MSLink::ApproachingVehicleInformation > Approaching
void writeBlocks(OutputDevice &od) const
Write block items for this driveway.
SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const
Returns the index of the logic at the given simulation step.
The parent class for traffic light logics.
Static storage of an output device and its base (abstract) implementation.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
link: the index of the link within the traffic light
bool isNormal() const
return whether this edge is an internal edge
LinkInfo(MSLink *link)
constructor
MSPhaseDefinition myCurrentPhase
The current phase.
std::vector< MSEdge * > MSEdgeVector
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
SUMOTime getOffsetFromIndex(int index) const
Returns the position (start of a phase during a cycle) from of a given step.
const MSRouteIterator & getCurrentRouteEdge() const
Returns an iterator pointing to the current edge in this vehicles route.
virtual const ConstMSEdgeVector::const_iterator & getCurrentRouteEdge() const =0
Returns an iterator pointing to the current edge in this vehicles route.
Representation of a lane in the micro simulation.
The definition of a single phase of a tls logic.
virtual const MSJunctionLogic * getLogic() const
bool myUniqueDriveWay
whether there is only a single DriveWay following this link
static std::string getTLLinkID(MSLink *link)
return logicID_linkIndex
MSRouteIterator end() const
Returns the end of the list of edges to pass.
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool overlap(const DriveWay &other) const
Wether this driveway overlaps with the given one.
int getCurrentPhaseIndex() const
Returns the current index within the program.
std::string getID() const
return id for this railsignal-link
SumoXMLNodeType getType() const
return the type of this Junction
~MSRailSignal()
Destructor.