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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // A rail signal logic
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <cassert>
26 #include <utility>
27 #include <vector>
28 #include <bitset>
30 #include <microsim/MSNet.h>
31 #include <microsim/MSEdge.h>
32 #include <microsim/MSLink.h>
33 #include <microsim/MSVehicle.h>
34 #include "MSTrafficLightLogic.h"
35 #include "MSRailSignal.h"
36 #include <microsim/MSLane.h>
37 #include "MSPhaseDefinition.h"
38 #include "MSTLLogicControl.h"
39 
40 // typical block length in germany on main lines is 3-5km on branch lines up to 7km
41 // special branches that are used by one train exclusively could also be up to 20km in length
42 // minimum block size in germany is 37.5m (LZB)
43 // larger countries (USA, Russia) might see blocks beyond 20km)
44 #define MAX_BLOCK_LENGTH 20000
45 #define MAX_SIGNAL_WARNINGS 10
46 
47 //#define DEBUG_SUCCEEDINGBLOCKS
48 #define DEBUG_COND (getID() == "disabled")
49 
50 // ===========================================================================
51 // static value definitions
52 // ===========================================================================
54 
55 class ApproachingVehicleInformation;
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
60  const std::string& id, const std::string& programID,
61  const std::map<std::string, std::string>& parameters) :
62  MSTrafficLightLogic(tlcontrol, id, programID, TLTYPE_RAIL_SIGNAL, DELTA_T, parameters),
63  myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X'), -1) { // dummy phase
65 }
66 
67 void
69  assert(myLanes.size() > 0);
70  LinkVectorVector::iterator i2; //iterator of the link indices of this junction (most likely there is just one link per index)
71  // find all outgoing lanes from the junction and its succeeding lanes leading to the next rail signal
72  // and find for every link at the junction all lanes leading from a previous signal to this link
73  for (i2 = myLinks.begin(); i2 != myLinks.end(); ++i2) { //for every link index
74  const LinkVector& links = *i2;
75  LinkVector::const_iterator i; //iterator of the links that belong to the same link index
76  for (i = links.begin(); i != links.end(); i++) { //for every link that belongs to the current index
77  MSLink* link = (*i);
78  MSLane* toLane = link->getLane(); //the lane this link is leading to
79  myLinksToLane[toLane].push_back(link);
80  myLinkIndices[link] = (int)std::distance(myLinks.begin(), i2); //assign the index of link to link
81 
82  //find all lanes leading from a previous signal to link (we presume that there exists only one path from a previous signal to link)
83  std::vector<const MSLane*> afferentBlock; //the vector of lanes leading from a previous signal to link
84  bool noRailSignal = true; //true if the considered lane is not outgoing from a rail signal
85  //get the approaching lane of the link
86  const MSLane* approachingLane = link->getLaneBefore(); //the lane this link is coming from
87  afferentBlock.push_back(approachingLane);
88  const MSLane* currentLane = approachingLane;
89  //look recursively for all lanes that lie before approachingLane and add them to afferentBlock until a rail signal is found
90  double blockLength = approachingLane->getLength();
91  while (noRailSignal) {
92  std::vector<MSLane::IncomingLaneInfo> incomingLanes = currentLane->getIncomingLanes();
93  // ignore incoming lanes for non-rail classes
94  for (auto it = incomingLanes.begin(); it != incomingLanes.end();) {
95  if (((*it).lane->getPermissions() & SVC_RAIL_CLASSES) == 0) {
96  it = incomingLanes.erase(it);
97  } else {
98  it++;
99  }
100  }
101  MSLane* precedentLane;
102  if (!incomingLanes.empty()) {
103  precedentLane = incomingLanes.front().lane;
104  } else {
105  precedentLane = nullptr;
106  }
107  if (precedentLane == nullptr) { //if there is no preceeding lane
108  noRailSignal = false;
109  } else if (blockLength >= MAX_BLOCK_LENGTH) { // avoid huge blocks
110  WRITE_WARNING("Block before rail signal junction '" + getID() +
111  "' exceeds maximum length (stopped searching at lane '" + precedentLane->getID() + "' after " + toString(blockLength) + "m).");
112  noRailSignal = false;
113  } else {
114  const MSJunction* junction = precedentLane->getEdge().getToJunction();
115  if ((junction != nullptr) && (junction->getType() == NODETYPE_RAIL_SIGNAL || junction->getType() == NODETYPE_TRAFFIC_LIGHT)) { //if this junction exists and if it has a rail signal
116  noRailSignal = false;
117  } else {
118  afferentBlock.push_back(precedentLane);
119  blockLength += precedentLane->getLength();
120  currentLane = precedentLane;
121  }
122  }
123  }
124  myAfferentBlocks[link] = afferentBlock;
125 
126  //find all lanes leading from toLane to the next signal if it was not already done
127  if (std::find(myOutgoingLanes.begin(), myOutgoingLanes.end(), toLane) == myOutgoingLanes.end()) { //if toLane was not already contained in myOutgoingLanes
128  myOutgoingLanes.push_back(toLane);
129  std::vector<const MSLane*> succeedingBlock; //the vector of lanes leading to the next rail signal
130  succeedingBlock.push_back(toLane);
131  currentLane = toLane;
132  bool noRailSignalLocal = true; //true if the considered lane is not ending at a rail signal
133  double blockLength = toLane->getLength();
134  while (noRailSignalLocal) {
135  //check first if the current lane is ending at a rail signal
136  std::vector<MSLink*> outGoingLinks = currentLane->getLinkCont();
137  std::vector<MSLink*>::const_iterator j;
138  for (j = outGoingLinks.begin(); j != outGoingLinks.end(); j++) {
139  const MSJunction* junction = currentLane->getEdge().getToJunction();
140  if ((junction != nullptr) && (junction->getType() == NODETYPE_RAIL_SIGNAL || junction->getType() == NODETYPE_TRAFFIC_LIGHT)) { //if this junctions exists and if it has a rail signal
141  noRailSignalLocal = false;
142  break;
143  }
144  }
145  if (noRailSignalLocal) { //if currentLane is not ending at a railSignal
146  //get the next lane
147  std::vector<const MSLane*> outGoingLanes;
148  // ignore outgoing lanes for non-rail classes
149  for (auto it : currentLane->getOutgoingViaLanes()) {
150  if ((it.first->getPermissions() & SVC_RAIL_CLASSES) != 0) {
151  outGoingLanes.push_back(it.first);
152  }
153  }
154  if (outGoingLanes.size() == 0) { //if the current lane has no outgoing lanes (deadend)
155  noRailSignalLocal = false;
156  } else if (blockLength > MAX_BLOCK_LENGTH) {
157  WRITE_WARNING("Block after rail signal junction '" + getID() +
158  "' exceeds maximum length (stopped searching at lane '" + currentLane->getID() + "' after " + toString(blockLength) + "m).");
159  noRailSignalLocal = false;
160  } else {
161  if (outGoingLanes.size() > 1) {
163  WRITE_WARNING("Rail lane '" + currentLane->getID() + "' has more than one outgoing lane but does not have a rail signal at its end");
164  } else if (myNumWarnings == MAX_SIGNAL_WARNINGS) {
165  WRITE_WARNING("Suppressing further signal warnings ...");
166  }
167  myNumWarnings++;
168  }
169  const MSLane* nextLane = outGoingLanes.front();
170  succeedingBlock.push_back(nextLane);
171  blockLength += nextLane->getLength();
172  currentLane = nextLane;
173  }
174  }
175  }
176  mySucceedingBlocks[toLane] = succeedingBlock;
177  }
178  }
179  }
180 #ifdef DEBUG_SUCCEEDINGBLOCKS
181  if (DEBUG_COND) {
182  std::cout << "railSignal=" << getID() << " mySucceedingBlocks:\n";
183  for (auto item : mySucceedingBlocks) {
184  std::cout << " toLane=" << item.first->getID() << " succ=" << toString(item.second) << "\n";
185  }
186  }
187 #endif
188 
189 
190  for (std::map<MSLane*, std::vector<const MSLane*> >::iterator it = mySucceedingBlocks.begin(); it != mySucceedingBlocks.end(); it++) {
191  std::queue<const MSLane*> revLanes;
192  for (std::vector<const MSLane*>::iterator laneIt = it->second.begin(); laneIt != it->second.end(); laneIt++) {
193  const MSLane* lane = *laneIt;
194 
195  const MSEdge* reverseEdge = lane->getEdge().getBidiEdge();
196  if (reverseEdge != nullptr) {
197  const MSLane* revLane = reverseEdge->getLanes()[0];
198  revLanes.push(revLane);
199  const MSLane* pred = revLane->getCanonicalPredecessorLane();
200  if (pred != nullptr) {
201  const MSLink* msLink = pred->getLinkTo(revLane);
202  mySucceedingBlocksIncommingLinks[lane] = msLink;
203  }
204  }
205  }
206 
207  while (!revLanes.empty()) {
208  const MSLane* revLane = revLanes.front();
209  it->second.push_back(revLane);
210  revLanes.pop();
211  }
212  }
213 
214  updateCurrentPhase(); //check if this is necessary or if will be done already at another stage
215  setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
216 }
217 
218 
220 
221 
222 // ----------- Handling of controlled links
223 void
227 }
228 
229 
230 // ------------ Switching and setting current rows
231 SUMOTime
234  setTrafficLightSignals(MSNet::getInstance()->getCurrentTimeStep());
235  return DELTA_T;
236 }
237 
238 std::string
240  std::string state(myLinks.size(), 'G'); //the state of the phase definition (all signal are green)
241  for (MSLane* lane : myOutgoingLanes) {
242  //check if the succeeding block is used by a train
243  bool succeedingBlockOccupied = false;
244  const std::vector<const MSLane*>& block = mySucceedingBlocks.at(lane);
245  for (const MSLane* l : block) {
246  if (!l->isEmpty()) { //if this lane is not empty
247  succeedingBlockOccupied = true;
248  break;
249  }
250  }
251  if (!succeedingBlockOccupied) {
252  // check whether approaching vehicles reserve the block
253  std::map<const MSLane*, const MSLink*>::iterator it = mySucceedingBlocksIncommingLinks.find(lane);
254  if (it != mySucceedingBlocksIncommingLinks.end()) {
255  for (auto apprIt : it->second->getApproaching()) {
256  MSLink::ApproachingVehicleInformation info = apprIt.second;
257  if (info.arrivalSpeedBraking > 0) {
258  succeedingBlockOccupied = true;
259  break;
260  }
261  }
262 
263  }
264  }
265 
266  /*-if the succeeding block is occupied the signals for all links leading to lane will be set to red.
267  -if the succeeding block is not occupied and all blocks leading to lane are not occupied all signal
268  will keep green.
269  -if the succeeding block is not occupied and there is only one block leading to lane its signal will
270  keep green (no matter if this block is occupied or not).
271  -if the succeeding block is not occupied and there is more than one block leading to lane and some
272  of them are occupied the signals for all links leading to lane, except one whose corresponding block
273  is occupied, will be set to red. the signal for the remaining block will keep green*/
274  if (succeedingBlockOccupied) { //if the succeeding block is used by a train
275  std::vector<MSLink*>::const_iterator k;
276  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to this lane
277  state.replace(myLinkIndices[*k], 1, "r"); //set the signal of the link (*k) to red
278  }
279  } else {
280  if (myLinksToLane[lane].size() > 1) { //if there is more than one link leading to lane
281  bool hasOccupiedBlock = false;
282  std::vector<MSLink*>::const_iterator k;
283  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to lane
284  std::vector<const MSLane*>::const_iterator l;
285  for (l = myAfferentBlocks[(*k)].begin(); l != myAfferentBlocks[(*k)].end(); l++) { //for every lane of the block leading from a previous signal to the link (*k)
286  if (!(*l)->isEmpty()) { //if this lane is not empty
287  hasOccupiedBlock = true;
288  //set the signals for all links leading to lane, except for (*k), to red; the signal for (*k) will remain green
289  std::vector<MSLink*>::const_iterator m;
290  for (m = myLinksToLane[lane].begin(); m != myLinksToLane[lane].end(); m++) { //for every link leading to lane
291  if (*m != *k) { //if this link is not the one corresponding to occupiedBlock
292  state.replace(myLinkIndices[*m], 1, "r"); //set the signal of this link to red
293  }
294  }
295  break; // we don't have to check the other lanes of this block anymore
296  }
297  }
298  if (hasOccupiedBlock) { //we don't have to check the other blocks anymore
299  break;
300  }
301  }
302  }
303  }
304  }
305  return state;
306 }
307 
308 
309 void
312 }
313 
314 
315 // ------------ Static Information Retrieval
316 int
318  return 0;
319 }
320 
323  return myPhases;
324 }
325 
326 const MSPhaseDefinition&
328  return myCurrentPhase;
329 }
330 
331 // ------------ Dynamic Information Retrieval
332 int
334  return 0;
335 }
336 
337 const MSPhaseDefinition&
339  return myCurrentPhase;
340 }
341 
342 // ------------ Conversion between time and phase
343 SUMOTime
345  return 0;
346 }
347 
348 SUMOTime
350  return 0;
351 }
352 
353 int
355  return 0;
356 }
357 
358 
359 /****************************************************************************/
360 
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:785
Builds detectors for microsim.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:640
long long int SUMOTime
Definition: SUMOTime.h:36
void updateCurrentPhase()
updates the current phase of the signal
const MSPhaseDefinition & getPhase(int givenstep) const
Returns the definition of the phase from the given position within the plan.
The base class for an intersection.
Definition: MSJunction.h:61
std::map< MSLane *, std::vector< MSLink * > > myLinksToLane
A map that maps an outgoing lane from the junction to its set of links that lead to this lane...
Definition: MSRailSignal.h:205
const std::vector< MSLane * > & getLanes() const
Returns this edge&#39;s lanes.
Definition: MSEdge.h:162
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).
Definition: MSNet.cpp:165
#define SUMO_MAX_CONNECTIONS
the maximum number of connections across an intersection
Definition: StdDefs.h:44
SUMOTime DELTA_T
Definition: SUMOTime.cpp:35
double getLength() const
Returns the lane&#39;s length.
Definition: MSLane.h:514
std::map< const MSLane *, const MSLink * > mySucceedingBlocksIncommingLinks
A map of lanes to links of approaching vehicles of succeeding blocks.
Definition: MSRailSignal.h:214
MSLink * getLinkTo(const MSLane *) const
returns the link to the given lane or 0, if it is not connected
Definition: MSLane.cpp:1982
MSLane * getCanonicalPredecessorLane() const
Definition: MSLane.cpp:2443
const std::string & getID() const
Returns the id.
Definition: Named.h:78
#define MAX_BLOCK_LENGTH
const MSJunction * getToJunction() const
Definition: MSEdge.h:347
bool setTrafficLightSignals(SUMOTime t) const
Applies the current signal states to controlled links.
const MSEdge * getBidiEdge() const
return opposite superposable/congruent edge, if it exist and 0 else
Definition: MSEdge.h:239
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:241
LaneVectorVector myLanes
The list of LaneVectors; each vector contains the incoming lanes that belong to the same link index...
std::map< MSLink *, int > myLinkIndices
A map that maps a link to its link index.
Definition: MSRailSignal.h:202
static int myNumWarnings
Definition: MSRailSignal.h:228
A class that stores and controls tls and switching of their programs.
A road/street connecting two junctions.
Definition: MSEdge.h:75
void setState(const std::string &_state)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
std::vector< MSLane * > myOutgoingLanes
The set of lanes going out from the junction.
Definition: MSRailSignal.h:199
SUMOTime myDefaultCycleTime
The cycle time (without changes)
void init(NLDetectorBuilder &nb)
Initialises the rail signal with information about adjacent rail signals.
classes which drive on tracks
Phases myPhases
The list of phases this logic uses.
Definition: MSRailSignal.h:223
const Phases & getPhases() const
Returns the phases of this tls program.
const MSPhaseDefinition & getCurrentPhaseDef() const
Returns the definition of the current phase.
virtual void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
std::map< MSLane *, std::vector< const MSLane * > > mySucceedingBlocks
A map that maps an outgoing lane from the junction to its vector of lanes leading to the next signal...
Definition: MSRailSignal.h:211
int getPhaseNumber() const
Returns the number of phases.
#define MAX_SIGNAL_WARNINGS
const std::vector< std::pair< const MSLane *, const MSEdge * > > getOutgoingViaLanes() const
get the list of outgoing lanes
Definition: MSLane.cpp:2495
SUMOTime trySwitch()
Switches to the next phase.
#define DEBUG_COND
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 > &parameters)
Constructor.
void adaptLinkInformationFrom(const MSTrafficLightLogic &logic)
Applies information about controlled links and lanes from the given logic.
SUMOTime getPhaseIndexAtTime(SUMOTime simStep) const
Returns the index of the logic at the given simulation step.
std::string getAppropriateState()
returns the state of the signal that actually required
The parent class for traffic light logics.
MSPhaseDefinition myCurrentPhase
The current phase.
Definition: MSRailSignal.h:226
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1975
std::map< MSLink *, std::vector< const MSLane * > > myAfferentBlocks
A map that maps a link from the junction to its vector of lanes leading from a previous signal to thi...
Definition: MSRailSignal.h:208
SUMOTime getOffsetFromIndex(int index) const
Returns the position (start of a phase during a cycle) from of a given step.
The definition of a single phase of a tls logic.
Representation of a lane in the micro simulation.
Definition: MSLane.h:78
int getCurrentPhaseIndex() const
Returns the current index within the program.
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:127
~MSRailSignal()
Destructor.