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& subid,
61  const std::map<std::string, std::string>& parameters) :
62  MSTrafficLightLogic(tlcontrol, id, subid, DELTA_T, parameters),
63  myCurrentPhase(DELTA_T, std::string(SUMO_MAX_CONNECTIONS, 'X')) { // 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 = 0;
106  }
107  if (precedentLane == 0) { //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 != 0) && (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 != 0) && (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 != 0) {
197  const MSLane* revLane = reverseEdge->getLanes()[0];
198  revLanes.push(revLane);
199  const MSLane* pred = revLane->getCanonicalPredecessorLane();
200  if (pred != 0) {
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  const MSLink* inCommingLing = it->second;
256  const std::map<const SUMOVehicle*, MSLink::ApproachingVehicleInformation, ComparatorIdLess> approaching = inCommingLing->getApproaching();
257  for (auto apprIt : approaching) {
258  MSLink::ApproachingVehicleInformation info = apprIt.second;
259  if (info.arrivalSpeedBraking > 0) {
260  succeedingBlockOccupied = true;
261  break;
262  }
263  }
264 
265  }
266  }
267 
268  /*-if the succeeding block is occupied the signals for all links leading to lane will be set to red.
269  -if the succeeding block is not occupied and all blocks leading to lane are not occupied all signal
270  will keep green.
271  -if the succeeding block is not occupied and there is only one block leading to lane its signal will
272  keep green (no matter if this block is occupied or not).
273  -if the succeeding block is not occupied and there is more than one block leading to lane and some
274  of them are occupied the signals for all links leading to lane, except one whose corresponding block
275  is occupied, will be set to red. the signal for the remaining block will keep green*/
276  if (succeedingBlockOccupied) { //if the succeeding block is used by a train
277  std::vector<MSLink*>::const_iterator k;
278  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to this lane
279  state.replace(myLinkIndices[*k], 1, "r"); //set the signal of the link (*k) to red
280  }
281  } else {
282  if (myLinksToLane[lane].size() > 1) { //if there is more than one link leading to lane
283  bool hasOccupiedBlock = false;
284  std::vector<MSLink*>::const_iterator k;
285  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to lane
286  std::vector<const MSLane*>::const_iterator l;
287  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)
288  if (!(*l)->isEmpty()) { //if this lane is not empty
289  hasOccupiedBlock = true;
290  //set the signals for all links leading to lane, except for (*k), to red; the signal for (*k) will remain green
291  std::vector<MSLink*>::const_iterator m;
292  for (m = myLinksToLane[lane].begin(); m != myLinksToLane[lane].end(); m++) { //for every link leading to lane
293  if (*m != *k) { //if this link is not the one corresponding to occupiedBlock
294  state.replace(myLinkIndices[*m], 1, "r"); //set the signal of this link to red
295  }
296  }
297  break; // we don't have to check the other lanes of this block anymore
298  }
299  }
300  if (hasOccupiedBlock) { //we don't have to check the other blocks anymore
301  break;
302  }
303  }
304  }
305  }
306  }
307  return state;
308 }
309 
310 
311 void
314 }
315 
316 
317 // ------------ Static Information Retrieval
318 int
320  return 0;
321 }
322 
325  return myPhases;
326 }
327 
328 const MSPhaseDefinition&
330  return myCurrentPhase;
331 }
332 
333 // ------------ Dynamic Information Retrieval
334 int
336  return 0;
337 }
338 
339 const MSPhaseDefinition&
341  return myCurrentPhase;
342 }
343 
344 // ------------ Conversion between time and phase
345 SUMOTime
347  return 0;
348 }
349 
350 SUMOTime
352  return 0;
353 }
354 
355 int
357  return 0;
358 }
359 
360 
361 /****************************************************************************/
362 
const std::vector< IncomingLaneInfo > & getIncomingLanes() const
Definition: MSLane.h:762
Builds detectors for microsim.
MSEdge & getEdge() const
Returns the lane&#39;s edge.
Definition: MSLane.h:617
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:60
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:212
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:160
#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:507
std::map< const MSLane *, const MSLink * > mySucceedingBlocksIncommingLinks
A map of lanes to links of approaching vehicles of succeeding blocks.
Definition: MSRailSignal.h:221
MSLink * getLinkTo(const MSLane *) const
returns the link to the given lane or 0, if it is not connected
Definition: MSLane.cpp:1959
MSLane * getCanonicalPredecessorLane() const
Definition: MSLane.cpp:2421
const std::string & getID() const
Returns the id.
Definition: Named.h:69
#define MAX_BLOCK_LENGTH
const MSJunction * getToJunction() const
Definition: MSEdge.h:346
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:238
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
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:209
static int myNumWarnings
Definition: MSRailSignal.h:235
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:206
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:230
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:218
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:2473
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...
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:233
const MSLinkCont & getLinkCont() const
returns the container with all links !!!
Definition: MSLane.cpp:1952
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:215
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:71
MSRailSignal(MSTLLogicControl &tlcontrol, const std::string &id, const std::string &subid, const std::map< std::string, std::string > &parameters)
Constructor.
int getCurrentPhaseIndex() const
Returns the current index within the program.
SumoXMLNodeType getType() const
return the type of this Junction
Definition: MSJunction.h:126
~MSRailSignal()
Destructor.