SUMO - Simulation of Urban MObility
NBTrafficLightDefinition.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // The base class for traffic light logic definitions
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
12 // Copyright (C) 2001-2015 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <vector>
34 #include <string>
35 #include <algorithm>
36 #include <cassert>
37 #include <iterator>
39 #include <utils/common/ToString.h>
43 #include "NBTrafficLightLogic.h"
44 #include "NBOwnTLDef.h"
45 #include "NBContHelper.h"
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 // ===========================================================================
52 // static members
53 // ===========================================================================
54 const std::string NBTrafficLightDefinition::DefaultProgramID = "0";
55 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
60  const std::vector<NBNode*>& junctions, const std::string& programID,
61  SUMOTime offset, TrafficLightType type) :
62  Named(id),
63  myControlledNodes(junctions),
64  mySubID(programID), myOffset(offset),
65  myType(type),
66  myNeedsContRelationReady(false),
67  myRightOnRedConflictsReady(false) {
68  std::vector<NBNode*>::iterator i = myControlledNodes.begin();
69  while (i != myControlledNodes.end()) {
70  for (std::vector<NBNode*>::iterator j = i + 1; j != myControlledNodes.end();) {
71  if (*i == *j) {
72  j = myControlledNodes.erase(j);
73  } else {
74  j++;
75  }
76  }
77  i++;
78  }
80  for (std::vector<NBNode*>::const_iterator i = junctions.begin(); i != junctions.end(); i++) {
81  (*i)->addTrafficLight(this);
82  }
83 }
84 
85 
87  NBNode* junction, const std::string& programID, SUMOTime offset, TrafficLightType type) :
88  Named(id),
89  mySubID(programID),
90  myOffset(offset),
91  myType(type),
93  addNode(junction);
94 }
95 
96 
97 NBTrafficLightDefinition::NBTrafficLightDefinition(const std::string& id, const std::string& programID,
98  SUMOTime offset, TrafficLightType type) :
99  Named(id),
100  mySubID(programID),
101  myOffset(offset),
102  myType(type),
104 {}
105 
106 
108 
109 
112  // it is not really a traffic light if no incoming edge exists
113  if (amInvalid()) {
114  // make a copy of myControlledNodes because it will be modified;
115  std::vector<NBNode*> nodes = myControlledNodes;
116  for (std::vector<NBNode*>::iterator it = nodes.begin(); it != nodes.end(); it++) {
117  (*it)->removeTrafficLight(this);
118  }
119  WRITE_WARNING("The traffic light '" + getID() + "' does not control any links; it will not be build.");
120  return 0;
121  }
122  // compute the time needed to brake
123  unsigned int brakingTime = computeBrakingTime(oc.getFloat("tls.yellow.min-decel"));
124  // perform the computation depending on whether the traffic light
125  // definition was loaded or shall be computed new completely
126  if (oc.isSet("tls.yellow.time")) {
127  brakingTime = oc.getInt("tls.yellow.time");
128  }
129  NBTrafficLightLogic* ret = myCompute(ec, brakingTime);
130  ret->addParameter(getMap());
131  return ret;
132 }
133 
134 
135 bool
137  return myControlledLinks.size() == 0;
138 }
139 
140 
141 unsigned int
144  return (unsigned int)(vmax / minDecel);
145 }
146 
147 
148 void
150  // collect the information about participating edges and links
151  collectEdges();
152  collectLinks();
153 }
154 
155 
156 void
158  myIncomingEdges.clear();
159  myEdgesWithin.clear();
160  EdgeVector myOutgoing;
161  // collect the edges from the participating nodes
162  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
163  const EdgeVector& incoming = (*i)->getIncomingEdges();
164  copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
165  const EdgeVector& outgoing = (*i)->getOutgoingEdges();
166  copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
167  }
168  EdgeVector outer;
169  // check which of the edges are completely within the junction
170  // add them to the list of edges lying within the node
171  for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end(); ++j) {
172  NBEdge* edge = *j;
173  // an edge lies within the logic if it is outgoing as well as incoming
174  EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge);
175  if (k != myOutgoing.end()) {
176  myEdgesWithin.push_back(edge);
177  } else {
178  outer.push_back(edge);
179  }
180  }
181  // collect edges that are reachable from the outside
182  std::set<NBEdge*> reachable;
183  while (outer.size() > 0) {
184  std::vector<NBEdge::Connection>& cons = outer.back()->getConnections();
185  outer.pop_back();
186  for (std::vector<NBEdge::Connection>::iterator k = cons.begin(); k != cons.end(); k++) {
187  NBEdge* to = (*k).toEdge;
188  if (reachable.count(to) == 0) {
189  reachable.insert(to);
190  outer.push_back(to);
191  }
192  }
193  }
194  const bool uncontrolledWithin = OptionsCont::getOptions().getBool("tls.uncontrolled-within");
195  for (EdgeVector::iterator j = myEdgesWithin.begin(); j != myEdgesWithin.end(); ++j) {
196  NBEdge* edge = *j;
197  // edges that are marked as 'inner' will not get their own phase when
198  // computing traffic light logics (unless they cannot be reached from the outside at all)
199  if (myControlledInnerEdges.count(edge->getID()) == 0 && reachable.count(edge) == 1) {
200  edge->setIsInnerEdge();
201  if (uncontrolledWithin) {
202  myIncomingEdges.erase(find(myIncomingEdges.begin(), myIncomingEdges.end(), edge));
203  }
204  }
205  if (reachable.count(edge) == 0 && edge->getFirstNonPedestrianLaneIndex(NBNode::FORWARD, true) >= 0) {
206  WRITE_WARNING("Unreachable edge '" + edge->getID() + "' within tlLogic '" + getID() + "'");
207  }
208  }
209 }
210 
211 
212 bool
213 NBTrafficLightDefinition::mustBrake(const NBEdge* const from, const NBEdge* const to) const {
214  std::vector<NBNode*>::const_iterator i =
215  find_if(myControlledNodes.begin(), myControlledNodes.end(),
217  assert(i != myControlledNodes.end());
218  NBNode* node = *i;
219  if (!node->hasOutgoing(to)) {
220  return true; // !!!
221  }
222  // @todo recheck relevance of lane indices
223  return node->mustBrake(from, to, -1, -1, true);
224 }
225 
226 
227 bool
228 NBTrafficLightDefinition::mustBrake(const NBEdge* const possProhibitedFrom,
229  const NBEdge* const possProhibitedTo,
230  const NBEdge* const possProhibitorFrom,
231  const NBEdge* const possProhibitorTo,
232  bool regardNonSignalisedLowerPriority) const {
233  return forbids(possProhibitorFrom, possProhibitorTo,
234  possProhibitedFrom, possProhibitedTo,
235  regardNonSignalisedLowerPriority);
236 }
237 
238 
239 bool
241  const NBConnection& possProhibitor,
242  bool regardNonSignalisedLowerPriority) const {
243  return forbids(possProhibitor.getFrom(), possProhibitor.getTo(),
244  possProhibited.getFrom(), possProhibited.getTo(),
245  regardNonSignalisedLowerPriority);
246 }
247 
248 
249 bool
250 NBTrafficLightDefinition::forbids(const NBEdge* const possProhibitorFrom,
251  const NBEdge* const possProhibitorTo,
252  const NBEdge* const possProhibitedFrom,
253  const NBEdge* const possProhibitedTo,
254  bool regardNonSignalisedLowerPriority,
255  bool sameNodeOnly) const {
256  if (possProhibitorFrom == 0 || possProhibitorTo == 0 || possProhibitedFrom == 0 || possProhibitedTo == 0) {
257  return false;
258  }
259  // retrieve both nodes
260  std::vector<NBNode*>::const_iterator incoming =
261  find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorFrom));
262  std::vector<NBNode*>::const_iterator outgoing =
263  find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_outgoing_finder(possProhibitedTo));
264  assert(incoming != myControlledNodes.end());
265  NBNode* incnode = *incoming;
266  NBNode* outnode = *outgoing;
267  EdgeVector::const_iterator i;
268  if (incnode != outnode) {
269  if (sameNodeOnly) {
270  return false;
271  }
272  // the links are located at different nodes
273  const EdgeVector& ev1 = possProhibitedTo->getConnectedEdges();
274  // go through the following edge,
275  // check whether one of these connections is prohibited
276  for (i = ev1.begin(); i != ev1.end(); ++i) {
277  std::vector<NBNode*>::const_iterator outgoing2 =
279  if (outgoing2 == myControlledNodes.end()) {
280  continue;
281  }
282  NBNode* outnode2 = *outgoing2;
283  if (incnode != outnode2) {
284  continue;
285  }
286  bool ret1 = incnode->foes(possProhibitorTo, *i,
287  possProhibitedFrom, possProhibitedTo);
288  bool ret2 = incnode->forbids(possProhibitorFrom, possProhibitorTo,
289  possProhibitedTo, *i,
290  regardNonSignalisedLowerPriority);
291  bool ret = ret1 || ret2;
292  if (ret) {
293  return true;
294  }
295  }
296 
297  const EdgeVector& ev2 = possProhibitorTo->getConnectedEdges();
298  // go through the following edge,
299  // check whether one of these connections is prohibited
300  for (i = ev2.begin(); i != ev2.end(); ++i) {
301  std::vector<NBNode*>::const_iterator incoming2 =
302  find_if(myControlledNodes.begin(), myControlledNodes.end(), NBContHelper::node_with_incoming_finder(possProhibitorTo));
303  if (incoming2 == myControlledNodes.end()) {
304  continue;
305  }
306  NBNode* incnode2 = *incoming2;
307  if (incnode2 != outnode) {
308  continue;
309  }
310  bool ret1 = incnode2->foes(possProhibitorTo, *i,
311  possProhibitedFrom, possProhibitedTo);
312  bool ret2 = incnode2->forbids(possProhibitorTo, *i,
313  possProhibitedFrom, possProhibitedTo,
314  regardNonSignalisedLowerPriority);
315  bool ret = ret1 || ret2;
316  if (ret) {
317  return true;
318  }
319  }
320  return false;
321  }
322  // both links are located at the same node
323  // check using this node's information
324  return incnode->forbids(possProhibitorFrom, possProhibitorTo,
325  possProhibitedFrom, possProhibitedTo,
326  regardNonSignalisedLowerPriority);
327 }
328 
329 
330 bool
331 NBTrafficLightDefinition::foes(const NBEdge* const from1, const NBEdge* const to1,
332  const NBEdge* const from2, const NBEdge* const to2) const {
333  if (to1 == 0 || to2 == 0) {
334  return false;
335  }
336  // retrieve both nodes (it is possible that a connection
337  std::vector<NBNode*>::const_iterator incoming =
338  find_if(myControlledNodes.begin(), myControlledNodes.end(),
340  std::vector<NBNode*>::const_iterator outgoing =
341  find_if(myControlledNodes.begin(), myControlledNodes.end(),
343  assert(incoming != myControlledNodes.end());
344  NBNode* incnode = *incoming;
345  NBNode* outnode = *outgoing;
346  if (incnode != outnode) {
347  return false;
348  }
349  return incnode->foes(from1, to1, from2, to2);
350 }
351 
352 
353 void
355  if (std::find(myControlledNodes.begin(), myControlledNodes.end(), node) == myControlledNodes.end()) {
356  myControlledNodes.push_back(node);
358  }
359  node->addTrafficLight(this);
360 }
361 
362 
363 void
365  std::vector<NBNode*>::iterator i = std::find(myControlledNodes.begin(), myControlledNodes.end(), node);
366  if (i != myControlledNodes.end()) {
367  myControlledNodes.erase(i);
368  }
369  // !!! remove in node?
370 }
371 
372 
373 void
374 NBTrafficLightDefinition::addControlledInnerEdges(const std::vector<std::string>& edges) {
375  myControlledInnerEdges.insert(edges.begin(), edges.end());
376 }
377 
378 
379 std::vector<std::string>
381  return std::vector<std::string>(myControlledInnerEdges.begin(), myControlledInnerEdges.end());
382 }
383 
384 
385 const EdgeVector&
387  return myIncomingEdges;
388 }
389 
390 
391 void
393  myControlledLinks.clear();
394  // build the list of links which are controled by the traffic light
395  for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
396  NBEdge* incoming = *i;
397  unsigned int noLanes = incoming->getNumLanes();
398  for (unsigned int j = 0; j < noLanes; j++) {
399  std::vector<NBEdge::Connection> connected = incoming->getConnectionsFromLane(j);
400  for (std::vector<NBEdge::Connection>::iterator k = connected.begin(); k != connected.end(); k++) {
401  const NBEdge::Connection& el = *k;
402  if (incoming->mayBeTLSControlled(el.fromLane, el.toEdge, el.toLane)) {
403  if (el.toEdge != 0 && el.toLane >= (int) el.toEdge->getNumLanes()) {
404  throw ProcessError("Connection '" + incoming->getID() + "_" + toString(j) + "->" + el.toEdge->getID() + "_" + toString(el.toLane) + "' yields in a not existing lane.");
405  }
406  int tlIndex = (int)myControlledLinks.size();
407  myControlledLinks.push_back(NBConnection(incoming, el.fromLane, el.toEdge, el.toLane, tlIndex));
408  }
409  }
410  }
411  }
412 }
413 
414 
415 bool
416 NBTrafficLightDefinition::needsCont(const NBEdge* fromE, const NBEdge* toE, const NBEdge* otherFromE, const NBEdge* otherToE) const {
419  assert(myNeedsContRelationReady);
420  }
421  return std::find(myNeedsContRelation.begin(), myNeedsContRelation.end(),
422  StreamPair(fromE, toE, otherFromE, otherToE)) != myNeedsContRelation.end();
423 }
424 
425 
426 void
428  if (!amInvalid()) {
429  NBOwnTLDef dummy("dummy", myControlledNodes, 0, TLTYPE_STATIC);
430  dummy.initNeedsContRelation();
432  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
433  (*i)->removeTrafficLight(&dummy);
434  }
435  }
437 }
438 
439 
440 bool
441 NBTrafficLightDefinition::rightOnRedConflict(int index, int foeIndex) const {
443  NBOwnTLDef dummy("dummy", myControlledNodes, 0, TLTYPE_STATIC);
445  dummy.computeLogicAndConts(0, true);
447  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
448  (*i)->removeTrafficLight(&dummy);
449  }
451  }
452  return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
453 }
454 
455 /****************************************************************************/
456 
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
int toLane
The lane the connections yields in.
Definition: NBEdge.h:166
TrafficLightType myType
The algorithm type for the traffic light.
long long int SUMOTime
Definition: SUMOTime.h:43
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:164
RightOnRedConflicts myRightOnRedConflicts
std::vector< std::string > getControlledInnerEdges() const
Retrieve the ids of edges explicitly controlled by the tls.
A SUMO-compliant built logic for a traffic light.
EdgeVector myIncomingEdges
The list of incoming edges.
virtual ~NBTrafficLightDefinition()
Destructor.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:70
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
Definition: NBEdge.cpp:1889
Used for sorting the cells by the begin time they describe.
Definition: NBNode.h:669
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
const std::map< std::string, std::string > & getMap() const
Returns the inner key/value map.
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
NBTrafficLightLogic * computeLogicAndConts(unsigned int brakingTimeSeconds, bool onlyConts=false)
helper function for myCompute
Definition: NBOwnTLDef.cpp:192
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:779
SUMOTime myOffset
The offset in the program.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
virtual void collectLinks()=0
Collects the links participating in this traffic light If a link could not be found.
EdgeVector getConnectedEdges() const
Returns the list of outgoing edges unsorted.
Definition: NBEdge.cpp:862
const std::string & getID() const
Returns the id.
Definition: Named.h:65
virtual void collectEdges()
Build the list of participating edges.
static const int FORWARD
edge directions (for pedestrian related stuff)
Definition: NBNode.h:183
std::set< std::string > myControlledInnerEdges
Set of inner edges that shall be controlled, though.
int fromLane
The lane the connections starts at.
Definition: NBEdge.h:162
NBTrafficLightLogic * compute(const NBEdgeCont &ec, OptionsCont &oc)
Computes the traffic light logic.
static SUMOReal maxSpeed(const EdgeVector &ev)
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:345
int getFirstNonPedestrianLaneIndex(int direction, bool exclusive=false) const
return the first lane with permissions other than SVC_PEDESTRIAN and 0
Definition: NBEdge.cpp:2404
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
static const std::string DefaultProgramID
unsigned int computeBrakingTime(SUMOReal minDecel) const
Computes the time vehicles may need to brake.
void addControlledInnerEdges(const std::vector< std::string > &edges)
Adds the given ids into the list of inner edges controlled by the tls.
bool mustBrake(const NBEdge *const from, const NBEdge *const to) const
Returns the information whether the described flow must let any other flow pass.
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
virtual void removeNode(NBNode *node)
Removes the given node from the list of controlled nodes.
Base class for objects which have an id.
Definition: Named.h:45
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority, bool sameNodeOnly=false) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
void addParameter(const std::string &key, const std::string &value)
Adds a parameter.
bool needsCont(const NBEdge *fromE, const NBEdge *toE, const NBEdge *otherFromE, const NBEdge *otherToE) const
void addTrafficLight(NBTrafficLightDefinition *tlDef)
Adds a traffic light to the list of traffic lights that control this node.
Definition: NBNode.cpp:312
bool mustBrake(const NBEdge *const from, const NBEdge *const to, int fromLane, int toLane, bool includePedCrossings) const
Returns the information whether the described flow must let any other flow pass.
Definition: NBNode.cpp:1243
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
A storage for options typed value containers)
Definition: OptionsCont.h:108
void setIsInnerEdge()
Marks this edge being within an intersection.
Definition: NBEdge.h:866
NBEdge * getTo() const
returns the to-edge (end of the connection)
Represents a single node (junction) during network building.
Definition: NBNode.h:74
virtual NBTrafficLightLogic * myCompute(const NBEdgeCont &ec, unsigned int brakingTime)=0
Computes the traffic light logic finally in dependence to the type.
#define SUMOReal
Definition: config.h:214
void initNeedsContRelation() const
Definition: NBOwnTLDef.cpp:581
data structure for caching needsCont information
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
NBTrafficLightDefinition(const std::string &id, const std::vector< NBNode * > &junctions, const std::string &programID, SUMOTime offset, TrafficLightType type)
Constructor.
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
Definition: NBNode.cpp:1339
void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
Definition: NBOwnTLDef.cpp:549
NBConnectionVector myControlledLinks
The list of controlled links.
EdgeVector myEdgesWithin
The list of edges within the area controlled by the tls.
std::string mySubID
The tls program&#39;s subid.
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
TrafficLightType
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool forbids(const NBEdge *const possProhibitorFrom, const NBEdge *const possProhibitorTo, const NBEdge *const possProhibitedFrom, const NBEdge *const possProhibitedTo, bool regardNonSignalisedLowerPriority) const
Returns the information whether "prohibited" flow must let "prohibitor" flow pass.
Definition: NBNode.cpp:1329
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
virtual void initNeedsContRelation() const