Eclipse SUMO - Simulation of Urban MObility
MSRailSignalControl.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 // Copyright (C) 2001-2024 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 /****************************************************************************/
18 // Centralized services for rail signal control (Singleton)
19 /****************************************************************************/
20 #include <config.h>
21 
22 #include <cassert>
23 #include <utility>
24 #include <vector>
25 #include <bitset>
26 #include <microsim/MSNet.h>
27 #include <microsim/MSRoute.h>
28 #include <microsim/MSEdge.h>
29 #include "MSRailSignal.h"
30 #include "MSRailSignalControl.h"
31 
32 
33 //#define DEBUG_REGISTER_DRIVEWAY
34 //#define DEBUG_SIGNALSTATE
35 //#define DEBUG_RECHECKGREEN
36 
37 // ===========================================================================
38 // static value definitions
39 // ===========================================================================
41 
42 // ===========================================================================
43 // method definitions
44 // ===========================================================================
46 {}
47 
50  if (myInstance == nullptr) {
53  }
54  return *myInstance;
55 }
56 
57 void
59  delete myInstance;
60  myInstance = nullptr;
61 }
62 
63 void
65  if (myInstance != nullptr) {
66  myInstance->myUsedEdges.clear();
69  }
70 }
71 
72 
74 }
75 
76 void
77 MSRailSignalControl::vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& /*info*/) {
78  if (isRailway(vehicle->getVClass())) {
80  for (const MSEdge* edge : vehicle->getRoute().getEdges()) {
81  myUsedEdges.insert(edge);
82  if (myProtectedDriveways.count(edge) != 0) {
83  updateDriveways(edge);
84  }
85  }
86  }
87  if (to == MSNet::VehicleState::BUILT || (!vehicle->hasDeparted() && to == MSNet::VehicleState::NEWROUTE)) {
88  // @note we could delay initialization until the departure time
90  }
91  }
92 }
93 
94 
95 void
96 MSRailSignalControl::registerProtectedDriveway(MSRailSignal* rs, int driveWayID, const MSEdge* protectedBidi) {
97  myProtectedDriveways[protectedBidi].push_back(std::make_pair(rs, driveWayID));
98 #ifdef DEBUG_REGISTER_DRIVEWAY
99  std::cout << "MSRailSignalControl edge=" << protectedBidi->getID() << " assumed secure by driveway " << driveWayID << " at signal " << rs->getID() << "\n";
100 #endif
101 }
102 
103 void
105  for (auto item : myProtectedDriveways[used]) {
106  item.first->updateDriveway(item.second);
107  }
108  myProtectedDriveways.erase(used);
109 }
110 
111 
112 void
114  mySignals.push_back(signal);
115 }
116 
117 
118 void
120  if (mySwitchedGreenFlanks.size() > 0) {
121  for (const auto& item : mySwitchedGreenFlanks) {
122  for (const auto& item2 : mySwitchedGreenFlanks) {
123  if (item.second < item2.second) {
124  bool conflict = false;
125  std::pair<int, int> code(item.second, item2.second);
126  auto it = myDriveWayCompatibility.find(code);
127  if (it != myDriveWayCompatibility.end()) {
128  conflict = it->second;
129  } else {
130  // new driveway pair
131  const MSRailSignal* rs = static_cast<const MSRailSignal*>(item.first->getTLLogic());
132  const MSRailSignal* rs2 = static_cast<const MSRailSignal*>(item2.first->getTLLogic());
133  const MSRailSignal::DriveWay& dw = rs->retrieveDriveWay(item.second);
134  const MSRailSignal::DriveWay& dw2 = rs2->retrieveDriveWay(item2.second);
135  // overlap may return true if the driveways are consecutive forward sections
136  conflict = dw.flankConflict(dw2) || dw2.flankConflict(dw);
137  myDriveWayCompatibility[code] = conflict;
138 #ifdef DEBUG_RECHECKGREEN
139  std::cout << SIMTIME << " new code " << code.first << "," << code.second << " conflict=" << conflict << " dw=" << toString(dw.myRoute) << " dw2=" << toString(dw2.myRoute) << "\n";
140 #endif
141  }
142  if (conflict) {
143  MSRailSignal* rs = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item.first->getTLLogic()));
144  MSRailSignal* rs2 = const_cast<MSRailSignal*>(static_cast<const MSRailSignal*>(item2.first->getTLLogic()));
145  const MSRailSignal::Approaching& veh = rs->getClosest(item.first);
146  const MSRailSignal::Approaching& veh2 = rs2->getClosest(item2.first);
147  if (MSRailSignal::DriveWay::mustYield(veh, veh2)) {
148  std::string state = rs->getCurrentPhaseDef().getState();
149  state[item.first->getTLIndex()] = 'r';
150  const_cast<MSPhaseDefinition&>(rs->getCurrentPhaseDef()).setState(state);
152 #ifdef DEBUG_RECHECKGREEN
153  std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first)
154  << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n";
155 #endif
156 #ifdef DEBUG_SIGNALSTATE
157  if (DEBUG_HELPER(rs)) {
158  std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item.first)
159  << " (" << veh.first->getID() << " yields to " << veh2.first->getID() << "\n";
160  }
161 #endif
162  } else {
163  std::string state = rs2->getCurrentPhaseDef().getState();
164  state[item2.first->getTLIndex()] = 'r';
165  const_cast<MSPhaseDefinition&>(rs2->getCurrentPhaseDef()).setState(state);
167 #ifdef DEBUG_RECHECKGREEN
168  std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first)
169  << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n";
170 #endif
171 #ifdef DEBUG_SIGNALSTATE
172  if (DEBUG_HELPER(rs2)) {
173  std::cout << SIMTIME << " reset to red " << getClickableTLLinkID(item2.first)
174  << " (" << veh2.first->getID() << " yields to " << veh.first->getID() << "\n";
175  }
176 #endif
177  }
178  }
179  }
180  }
181  }
182  mySwitchedGreenFlanks.clear();
183  }
184 }
185 
186 
187 /****************************************************************************/
#define DEBUG_HELPER(obj)
#define SIMTIME
Definition: SUMOTime.h:62
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
A road/street connecting two junctions.
Definition: MSEdge.h:77
VehicleState
Definition of a vehicle state.
Definition: MSNet.h:602
@ BUILT
The vehicle was built, but has not yet departed.
@ NEWROUTE
The vehicle got a new route.
@ DEPARTED
The vehicle has departed (was inserted into the network)
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:182
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
void addVehicleStateListener(VehicleStateListener *listener)
Adds a vehicle states listener.
Definition: MSNet.cpp:1241
The definition of a single phase of a tls logic.
const std::string & getState() const
Returns the state within this phase.
A signal for rails.
void addSignal(MSRailSignal *signal)
void vehicleStateChanged(const SUMOVehicle *const vehicle, MSNet::VehicleState to, const std::string &info="")
Called if a vehicle changes its state.
std::map< const MSEdge *, std::vector< std::pair< MSRailSignal *, int > > > myProtectedDriveways
map of driveways that must perform additional checks if the key edge is used by a train route
std::vector< MSRailSignal * > mySignals
list of all rail signals
MSRailSignalControl()
Constructor.
std::set< const MSEdge * > myUsedEdges
all rail edges that are part of a known route
void recheckGreen()
final check for driveway compatibility of signals that switched green in this step
static MSRailSignalControl * myInstance
static MSRailSignalControl & getInstance()
void updateDriveways(const MSEdge *used)
compute additioanl deadlock-check requirements for registered driveways
std::map< std::pair< int, int >, bool > myDriveWayCompatibility
static void clearState()
Perform resets events when quick-loading state.
std::vector< std::pair< MSLink *, int > > mySwitchedGreenFlanks
list of signals that switched green along with driveway index
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
static Approaching getClosest(MSLink *link)
get the closest vehicle approaching the given link
std::pair< const SUMOVehicle *const, const MSLink::ApproachingVehicleInformation > Approaching
Definition: MSRailSignal.h:254
const DriveWay & retrieveDriveWay(int numericalID) const
const MSPhaseDefinition & getCurrentPhaseDef() const override
Returns the definition of the current phase.
static void initDriveWays(const SUMOVehicle *ego, bool update)
const ConstMSEdgeVector & getEdges() const
Definition: MSRoute.h:124
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
Representation of a vehicle.
Definition: SUMOVehicle.h:60
virtual const MSRoute & getRoute() const =0
Returns the current route.
virtual bool hasDeparted() const =0
Returns whether this vehicle has departed.
std::vector< const MSEdge * > myRoute
list of edges for matching against train routes
Definition: MSRailSignal.h:291
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.