SUMO - Simulation of Urban MObility
NBLoadedSUMOTLDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A complete traffic light logic loaded from a sumo-net. (opted to reimplement
10 // since NBLoadedTLDef is quite vissim specific)
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
13 // Copyright (C) 2011-2016 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
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 <set>
35 #include <cassert>
36 #include <iterator>
38 #include <utils/common/ToString.h>
40 #include "NBTrafficLightLogic.h"
41 #include "NBOwnTLDef.h"
43 #include "NBLoadedSUMOTLDef.h"
44 #include "NBNode.h"
45 
46 #ifdef CHECK_MEMORY_LEAKS
47 #include <foreign/nvwa/debug_new.h>
48 #endif // CHECK_MEMORY_LEAKS
49 
50 // ===========================================================================
51 // method definitions
52 // ===========================================================================
53 
54 NBLoadedSUMOTLDef::NBLoadedSUMOTLDef(const std::string& id, const std::string& programID,
55  SUMOTime offset, TrafficLightType type) :
56  NBTrafficLightDefinition(id, programID, offset, type),
57  myTLLogic(0) {
58  myTLLogic = new NBTrafficLightLogic(id, programID, 0, offset, type);
59 }
60 
61 
63  // allow for adding a new program for the same def: take the programID from the new logic
64  NBTrafficLightDefinition(def->getID(), logic->getProgramID(), def->getOffset(), def->getType()),
66  myOriginalNodes(def->getNodes().begin(), def->getNodes().end()) {
67  assert(def->getOffset() == logic->getOffset());
68  assert(def->getType() == logic->getType());
70  myControlledNodes = def->getNodes();
71 }
72 
73 
75  delete myTLLogic;
76 }
77 
78 
80 NBLoadedSUMOTLDef::myCompute(int brakingTimeSeconds) {
81  // @todo what to do with those parameters?
82  UNUSED_PARAMETER(brakingTimeSeconds);
85  return new NBTrafficLightLogic(myTLLogic);
86 }
87 
88 
89 void
90 NBLoadedSUMOTLDef::addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex) {
91  assert(myTLLogic->getNumLinks() > 0); // logic should be loaded by now
92  if (linkIndex >= (int)myTLLogic->getNumLinks()) {
93  throw ProcessError("Invalid linkIndex " + toString(linkIndex) + " for traffic light '" + getID() +
94  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
95  }
96  NBConnection conn(from, fromLane, to, toLane, linkIndex);
97  // avoid duplicates
98  remove_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(conn));
99  myControlledLinks.push_back(conn);
100  addNode(from->getToNode());
101  addNode(to->getFromNode());
102  myOriginalNodes.insert(from->getToNode());
103  myOriginalNodes.insert(to->getFromNode());
104  // added connections are definitely controlled. make sure none are removed because they lie within the tl
105  // myControlledInnerEdges.insert(from->getID()); // @todo recheck: this appears to be obsolete
106  // set this information now so that it can be used while loading diffs
107  from->setControllingTLInformation(conn, getID());
108 }
109 
110 
111 void
113  // if nodes have been removed our links may have been invalidated as well
114  // since no logic will be built anyway there is no reason to inform any edges
115  if (amInvalid()) {
116  return;
117  }
118  // set the information about the link's positions within the tl into the
119  // edges the links are starting at, respectively
120  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
121  const NBConnection& c = *it;
122  if (c.getTLIndex() >= (int)myTLLogic->getNumLinks()) {
123  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
124  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
125  }
126  NBEdge* edge = c.getFrom();
127  if (edge != 0) {
129  }
130  }
131 }
132 
133 
134 void
136 
137 
138 void
139 NBLoadedSUMOTLDef::replaceRemoved(NBEdge* removed, int removedLane, NBEdge* by, int byLane) {
140  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
141  (*it).replaceFrom(removed, removedLane, by, byLane);
142  (*it).replaceTo(removed, removedLane, by, byLane);
143  }
144 }
145 
146 
147 void
148 NBLoadedSUMOTLDef::addPhase(SUMOTime duration, const std::string& state) {
149  myTLLogic->addStep(duration, state);
150 }
151 
152 
153 bool
155  if (myControlledLinks.size() == 0) {
156  return true;
157  }
158  // make sure that myControlledNodes are the original nodes
159  if (myControlledNodes.size() != myOriginalNodes.size()) {
160  return true;
161  }
162  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
163  if (myOriginalNodes.count(*i) != 1) {
164  return true;
165  }
166  }
167  return false;
168 }
169 
170 
171 void
172 NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
173  NBConnectionVector::iterator it = myControlledLinks.begin();
174  // find the connection but ignore its TLIndex since it might have been
175  // invalidated by an earlier removal
176  for (; it != myControlledLinks.end(); ++it) {
177  if (it->getFrom() == conn.getFrom() &&
178  it->getTo() == conn.getTo() &&
179  it->getFromLane() == conn.getFromLane() &&
180  it->getToLane() == conn.getToLane()) {
181  break;
182  }
183  }
184  if (it == myControlledLinks.end()) {
185  // a traffic light doesn't always controll all connections at a junction
186  // especially when using the option --tls.join
187  return;
188  }
189  const int removed = it->getTLIndex();
190  // remove the connection
191  myControlledLinks.erase(it);
192  if (reconstruct) {
193  // updating the edge is only needed for immediate use in NETEDIT.
194  // It may conflict with loading diffs
195  conn.getFrom()->setControllingTLInformation(conn, "");
196  // shift link numbers down so there is no gap
197  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
198  NBConnection& c = *it;
199  if (c.getTLIndex() > removed) {
200  c.setTLIndex(c.getTLIndex() - 1);
201  }
202  }
203  // update controlling information with new link numbers
205  // rebuild the logic
206  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
208  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
209  std::string newState = it->state;
210  newState.erase(newState.begin() + removed);
211  newLogic->addStep(it->duration, newState);
212  }
213  delete myTLLogic;
214  myTLLogic = newLogic;
215  }
216 }
217 
218 
219 void
221  myOffset = offset;
222  myTLLogic->setOffset(offset);
223 }
224 
225 
226 void
228  myType = type;
229  myTLLogic->setType(type);
230 }
231 
232 
233 void
235  if (myControlledLinks.size() == 0) {
237  }
238  myIncomingEdges.clear();
239  EdgeVector myOutgoing;
240  // collect the edges from the participating nodes
241  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
242  const EdgeVector& incoming = (*i)->getIncomingEdges();
243  copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
244  const EdgeVector& outgoing = (*i)->getOutgoingEdges();
245  copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
246  }
247  // check which of the edges are completely within the junction
248  // and which are uncontrolled as well (we already know myControlledLinks)
249  for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) {
250  NBEdge* edge = *j;
251  // an edge lies within the logic if it is outgoing as well as incoming
252  EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge);
253  if (k != myOutgoing.end()) {
254  if (myControlledInnerEdges.count(edge->getID()) == 0) {
255  bool controlled = false;
256  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
257  if ((*it).getFrom() == edge) {
258  controlled = true;
259  break;
260  }
261  }
262  if (controlled) {
263  myControlledInnerEdges.insert(edge->getID());
264  } else {
265  myEdgesWithin.push_back(edge);
266  (*j)->setIsInnerEdge();
267  ++j; //j = myIncomingEdges.erase(j);
268  continue;
269  }
270  }
271  }
272  ++j;
273  }
274 }
275 
276 
277 void
279  if (myControlledLinks.size() == 0) {
280  // maybe we only loaded a different program for a default traffic light.
281  // Try to build links now.
282  myOriginalNodes.insert(myControlledNodes.begin(), myControlledNodes.end());
283  collectAllLinks();
284  }
285 }
286 
287 
289 void
291  // avoid shifting twice if the edge is incoming and outgoing to a joined TLS
292  if (myShifted.count(edge) == 0) {
294  myShifted.insert(edge);
295  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
296  (*it).shiftLaneIndex(edge, offset);
297  }
298  }
299 }
300 
301 void
303  // XXX what to do if crossings are removed during network building?
304  const int size = myTLLogic->getNumLinks();
305  int noLinksAll = 0;
306  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
307  const NBConnection& c = *it;
309  noLinksAll = MAX2(noLinksAll, (int)c.getTLIndex() + 1);
310  }
311  }
312  int oldCrossings = 0;
313  // collect crossings
314  std::vector<NBNode::Crossing> crossings;
315  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
316  const std::vector<NBNode::Crossing>& c = (*i)->getCrossings();
317  // set tl indices for crossings
318  (*i)->setCrossingTLIndices(noLinksAll);
319  copy(c.begin(), c.end(), std::back_inserter(crossings));
320  noLinksAll += (int)c.size();
321  oldCrossings += (*i)->numCrossingsFromSumoNet();
322  }
323  const int newCrossings = (int)crossings.size() - oldCrossings;
324  if (newCrossings > 0) {
325  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
326  if (phases.size() > 0) {
327  if ((int)phases.front().state.size() == noLinksAll - newCrossings) {
328  // patch states for the newly added crossings
329 
330  // collect edges
331  EdgeVector fromEdges(size, (NBEdge*)0);
332  EdgeVector toEdges(size, (NBEdge*)0);
333  std::vector<int> fromLanes(size, 0);
334  collectEdgeVectors(fromEdges, toEdges, fromLanes);
335  const std::string crossingDefaultState(newCrossings, 'r');
336 
337  // rebuild the logic (see NBOwnTLDef.cpp::myCompute)
338  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
340  SUMOTime brakingTime = TIME2STEPS(3);
341  //std::cout << "patchIfCrossingsAdded for " << getID() << " numPhases=" << phases.size() << "\n";
342  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
343  if ((*it).state.find_first_of("yY") != std::string::npos) {
344  brakingTime = MAX2(brakingTime, it->duration);
345  }
346  NBOwnTLDef::addPedestrianPhases(newLogic, it->duration, it->state + crossingDefaultState, crossings, fromEdges, toEdges);
347  }
348  NBOwnTLDef::addPedestrianScramble(newLogic, noLinksAll, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
349 
350  delete myTLLogic;
351  myTLLogic = newLogic;
352  } else if ((int)phases.front().state.size() != noLinksAll) {
353  WRITE_WARNING("Could not patch tlLogic " + getID() + "for new crossings");
354  }
355  }
356  }
357 }
358 
359 
360 void
361 NBLoadedSUMOTLDef::collectEdgeVectors(EdgeVector& fromEdges, EdgeVector& toEdges, std::vector<int>& fromLanes) const {
362  assert(fromEdges.size() > 0);
363  assert(fromEdges.size() == toEdges.size());
364  const int size = (int)fromEdges.size();
365 
366  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
367  const NBConnection& c = *it;
369  if (c.getTLIndex() >= size) {
370  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
371  "' with " + toString(size) + " links.");
372  }
373  fromEdges[c.getTLIndex()] = c.getFrom();
374  toEdges[c.getTLIndex()] = c.getTo();
375  fromLanes[c.getTLIndex()] = c.getFromLane();
376  }
377  }
378 }
379 
380 
381 void
383  if (!amInvalid() && !myNeedsContRelationReady) {
384  myNeedsContRelation.clear();
385  myRightOnRedConflicts.clear();
386  const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
387  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
388  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
389  const std::string state = (*it).state;
390  for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
391  const NBConnection& c1 = *it1;
392  const int i1 = c1.getTLIndex();
393  if (i1 == NBConnection::InvalidTlIndex || state[i1] != 'g' || c1.getFrom() == 0 || c1.getTo() == 0) {
394  continue;
395  }
396  for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
397  const NBConnection& c2 = *it2;
398  const int i2 = c2.getTLIndex();
400  && i2 != i1
401  && (state[i2] == 'G' || state[i2] == 'g')
402  && c2.getFrom() != 0 && c2.getTo() != 0) {
403  const bool rightTurnConflict = NBNode::rightTurnConflict(
404  c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
405  const bool forbidden = forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin);
406  const bool isFoes = foes(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo());
407  if (forbidden || rightTurnConflict) {
408  myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
409  }
410  if (isFoes) {
411  myRightOnRedConflicts.insert(std::make_pair(i1, i2));
412  }
413  //std::cout << getID() << " i1=" << i1 << " i2=" << i2 << " rightTurnConflict=" << rightTurnConflict << " forbidden=" << forbidden << " isFoes=" << isFoes << "\n";
414  }
415  }
416  }
417  }
418  }
421 }
422 
423 
424 bool
425 NBLoadedSUMOTLDef::rightOnRedConflict(int index, int foeIndex) const {
426  if (amInvalid()) {
427  return false;
428  }
432  }
433  return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
434 }
435 
436 
437 /****************************************************************************/
438 
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:2102
TrafficLightType getType() const
get the algorithm type (static etc..)
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.
NBLoadedSUMOTLDef(const std::string &id, const std::string &programID, SUMOTime offset, TrafficLightType type)
Constructor.
int getTLIndex() const
Definition: NBConnection.h:101
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
void collectEdges()
Build the list of participating edges.
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
void setOffset(SUMOTime offset)
Sets the offset of this tls.
int getNumLinks()
Returns the number of participating links.
void closeBuilding()
closes the building process
RightOnRedConflicts myRightOnRedConflicts
A SUMO-compliant built logic for a traffic light.
TrafficLightType getType() const
get the algorithm type (static etc..)
EdgeVector myIncomingEdges
The list of incoming edges.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProgramID() const
Returns the ProgramID.
The representation of a single edge during network building.
Definition: NBEdge.h:70
class for identifying connections
int getFromLane() const
returns the from-lane
The base class for traffic light logic definitions.
void setOffset(SUMOTime offset)
Sets the offset of this tls.
T MAX2(T a, T b)
Definition: StdDefs.h:75
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
SUMOTime myOffset
The offset in the program.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:1368
void setTLIndex(int tlIndex)
Definition: NBConnection.h:106
SUMOTime getOffset()
Returns the offset.
#define new
Definition: debug_new.h:121
void setType(TrafficLightType type)
set the algorithm type (static etc..)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
virtual void collectEdges()
Build the list of participating edges.
static const int InvalidTlIndex
Definition: NBConnection.h:127
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
std::set< std::string > myControlledInnerEdges
Set of inner edges that shall be controlled, though.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
void patchIfCrossingsAdded()
repair the plan if controlled nodes received pedestrian crossings
std::set< NBNode * > myOriginalNodes
The original nodes for which the loaded logic is valid.
void initNeedsContRelation() const
static std::string addPedestrianPhases(NBTrafficLightLogic *logic, SUMOTime greenTime, std::string state, const std::vector< NBNode::Crossing > &crossings, const EdgeVector &fromEdges, const EdgeVector &toEdges)
add 1 or 2 phases depending on the presence of pedestrian crossings
Definition: NBOwnTLDef.cpp:441
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
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.
SUMOTime getOffset() const
Returns the offset of first switch.
std::set< NBEdge * > myShifted
set of edges with shifted lane indices (to avoid shifting twice)
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
static void addPedestrianScramble(NBTrafficLightLogic *logic, int noLinksAll, SUMOTime greenTime, SUMOTime yellowTime, const std::vector< NBNode::Crossing > &crossings, const EdgeVector &fromEdges, const EdgeVector &toEdges)
add an additional pedestrian phase if there are crossings that did not get green yet ...
Definition: NBOwnTLDef.cpp:662
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:371
void addPhase(SUMOTime duration, const std::string &state)
Adds a phase to the logic the new phase is inserted at the end of the list of already added phases...
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
int getToLane() const
returns the to-lane
void collectLinks()
Collects the links participating in this traffic light (only if not previously loaded) ...
NBEdge * getTo() const
returns the to-edge (end of the connection)
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
~NBLoadedSUMOTLDef()
Destructor.
data structure for caching needsCont information
void setType(TrafficLightType type)
Sets the algorithm type of this tls.
void collectEdgeVectors(EdgeVector &fromEdges, EdgeVector &toEdges, std::vector< int > &fromLanes) const
Collects the edges for each tlIndex.
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
NBConnectionVector myControlledLinks
The list of controlled links.
EdgeVector myEdgesWithin
The list of edges within the area controlled by the tls.
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset)
patches signal plans by modifying lane indices
NBTrafficLightLogic * myTLLogic
phases are added directly to myTLLogic which is then returned in myCompute()
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex)
Adds a connection and immediately informs the edges.
TrafficLightType
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.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:363