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),
92  myNeedsContRelationReady(false) {
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),
103  myNeedsContRelationReady(false)
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
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
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:215
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.
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