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  std::map<const SUMOVehicle*, MSLink::ApproachingVehicleInformation>::const_iterator apprIt = approaching.begin();
258  for (; apprIt != approaching.end(); apprIt++) {
259  MSLink::ApproachingVehicleInformation info = apprIt->second;
260  if (info.arrivalSpeedBraking > 0) {
261  succeedingBlockOccupied = true;
262  break;
263  }
264  }
265 
266  }
267  }
268 
269  /*-if the succeeding block is occupied the signals for all links leading to lane will be set to red.
270  -if the succeeding block is not occupied and all blocks leading to lane are not occupied all signal
271  will keep green.
272  -if the succeeding block is not occupied and there is only one block leading to lane its signal will
273  keep green (no matter if this block is occupied or not).
274  -if the succeeding block is not occupied and there is more than one block leading to lane and some
275  of them are occupied the signals for all links leading to lane, except one whose corresponding block
276  is occupied, will be set to red. the signal for the remaining block will keep green*/
277  if (succeedingBlockOccupied) { //if the succeeding block is used by a train
278  std::vector<MSLink*>::const_iterator k;
279  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to this lane
280  state.replace(myLinkIndices[*k], 1, "r"); //set the signal of the link (*k) to red
281  }
282  } else {
283  if (myLinksToLane[lane].size() > 1) { //if there is more than one link leading to lane
284  bool hasOccupiedBlock = false;
285  std::vector<MSLink*>::const_iterator k;
286  for (k = myLinksToLane[lane].begin(); k != myLinksToLane[lane].end(); k++) { //for every link leading to lane
287  std::vector<const MSLane*>::const_iterator l;
288  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)
289  if (!(*l)->isEmpty()) { //if this lane is not empty
290  hasOccupiedBlock = true;
291  //set the signals for all links leading to lane, except for (*k), to red; the signal for (*k) will remain green
292  std::vector<MSLink*>::const_iterator m;
293  for (m = myLinksToLane[lane].begin(); m != myLinksToLane[lane].end(); m++) { //for every link leading to lane
294  if (*m != *k) { //if this link is not the one corresponding to occupiedBlock
295  state.replace(myLinkIndices[*m], 1, "r"); //set the signal of this link to red
296  }
297  }
298  break; // we don't have to check the other lanes of this block anymore
299  }
300  }
301  if (hasOccupiedBlock) { //we don't have to check the other blocks anymore
302  break;
303  }
304  }
305  }
306  }
307  }
308  return state;
309 }
310 
311 
312 void
315 }
316 
317 
318 // ------------ Static Information Retrieval
319 int
321  return 0;
322 }
323 
326  return myPhases;
327 }
328 
329 const MSPhaseDefinition&
331  return myCurrentPhase;
332 }
333 
334 // ------------ Dynamic Information Retrieval
335 int
337  return 0;
338 }
339 
340 const MSPhaseDefinition&
342  return myCurrentPhase;
343 }
344 
345 // ------------ Conversion between time and phase
346 SUMOTime
348  return 0;
349 }
350 
351 SUMOTime
353  return 0;
354 }
355 
356 int
358  return 0;
359 }
360 
361 
362 /****************************************************************************/
363 
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:36
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:1947
MSLane * getCanonicalPredecessorLane() const
Definition: MSLane.cpp:2409
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:2461
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:1940
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.