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-2015 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(const NBEdgeCont& ec, unsigned int brakingTimeSeconds) {
81  // @todo what to do with those parameters?
82  UNUSED_PARAMETER(ec);
83  UNUSED_PARAMETER(brakingTimeSeconds);
86  return new NBTrafficLightLogic(myTLLogic);
87 }
88 
89 
90 void
91 NBLoadedSUMOTLDef::addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex) {
92  assert(myTLLogic->getNumLinks() > 0); // logic should be loaded by now
93  if (linkIndex >= (int)myTLLogic->getNumLinks()) {
94  throw ProcessError("Invalid linkIndex " + toString(linkIndex) + " for traffic light '" + getID() +
95  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
96  }
97  NBConnection conn(from, fromLane, to, toLane, linkIndex);
98  // avoid duplicates
99  remove_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(conn));
100  myControlledLinks.push_back(conn);
101  addNode(from->getToNode());
102  addNode(to->getFromNode());
103  myOriginalNodes.insert(from->getToNode());
104  myOriginalNodes.insert(to->getFromNode());
105  // added connections are definitely controlled. make sure none are removed because they lie within the tl
106  // myControlledInnerEdges.insert(from->getID()); // @todo recheck: this appears to be obsolete
107  // set this information now so that it can be used while loading diffs
108  from->setControllingTLInformation(conn, getID());
109 }
110 
111 
112 void
115 }
116 
117 
118 void
120  // if nodes have been removed our links may have been invalidated as well
121  // since no logic will be built anyway there is no reason to inform any edges
122  if (amInvalid()) {
123  return;
124  }
125  // set the information about the link's positions within the tl into the
126  // edges the links are starting at, respectively
127  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
128  const NBConnection& c = *it;
129  if (c.getTLIndex() >= (int)myTLLogic->getNumLinks()) {
130  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
131  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
132  }
133  NBEdge* edge = c.getFrom();
135  }
136 }
137 
138 
139 void
141 
142 
143 void
144 NBLoadedSUMOTLDef::replaceRemoved(NBEdge* removed, int removedLane, NBEdge* by, int byLane) {
145  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
146  (*it).replaceFrom(removed, removedLane, by, byLane);
147  (*it).replaceTo(removed, removedLane, by, byLane);
148  }
149 }
150 
151 
152 void
153 NBLoadedSUMOTLDef::addPhase(SUMOTime duration, const std::string& state) {
154  myTLLogic->addStep(duration, state);
155 }
156 
157 
158 bool
160  if (myControlledLinks.size() == 0) {
161  return true;
162  }
163  // make sure that myControlledNodes are the original nodes
164  if (myControlledNodes.size() != myOriginalNodes.size()) {
165  return true;
166  }
167  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
168  if (myOriginalNodes.count(*i) != 1) {
169  return true;
170  }
171  }
172  return false;
173 }
174 
175 
176 void
177 NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
178  NBConnectionVector::iterator it = myControlledLinks.begin();
179  // find the connection but ignore its TLIndex since it might have been
180  // invalidated by an earlier removal
181  for (; it != myControlledLinks.end(); ++it) {
182  if (it->getFrom() == conn.getFrom() &&
183  it->getTo() == conn.getTo() &&
184  it->getFromLane() == conn.getFromLane() &&
185  it->getToLane() == conn.getToLane()) {
186  break;
187  }
188  }
189  if (it == myControlledLinks.end()) {
190  // a traffic light doesn't always controll all connections at a junction
191  // especially when using the option --tls.join
192  return;
193  }
194  const int removed = it->getTLIndex();
195  // remove the connection
196  myControlledLinks.erase(it);
197  if (reconstruct) {
198  // updating the edge is only needed for immediate use in NETEDIT.
199  // It may conflict with loading diffs
200  conn.getFrom()->setControllingTLInformation(conn, "");
201  // shift link numbers down so there is no gap
202  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
203  NBConnection& c = *it;
204  if (c.getTLIndex() > removed) {
205  c.setTLIndex(c.getTLIndex() - 1);
206  }
207  }
208  // update controlling information with new link numbers
210  // rebuild the logic
211  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
213  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
214  std::string newState = it->state;
215  newState.erase(newState.begin() + removed);
216  newLogic->addStep(it->duration, newState);
217  }
218  delete myTLLogic;
219  myTLLogic = newLogic;
220  }
221 }
222 
223 
224 void
226  myOffset = offset;
227  myTLLogic->setOffset(offset);
228 }
229 
230 
231 void
233  myType = type;
234  myTLLogic->setType(type);
235 }
236 
237 
238 void
240  if (myControlledLinks.size() == 0) {
242  }
243  myIncomingEdges.clear();
244  EdgeVector myOutgoing;
245  // collect the edges from the participating nodes
246  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
247  const EdgeVector& incoming = (*i)->getIncomingEdges();
248  copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
249  const EdgeVector& outgoing = (*i)->getOutgoingEdges();
250  copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
251  }
252  // check which of the edges are completely within the junction
253  // and which are uncontrolled as well (we already know myControlledLinks)
254  for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) {
255  NBEdge* edge = *j;
256  // an edge lies within the logic if it is outgoing as well as incoming
257  EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge);
258  if (k != myOutgoing.end()) {
259  if (myControlledInnerEdges.count(edge->getID()) == 0) {
260  bool controlled = false;
261  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
262  if ((*it).getFrom() == edge) {
263  controlled = true;
264  break;
265  }
266  }
267  if (controlled) {
268  myControlledInnerEdges.insert(edge->getID());
269  } else {
270  myEdgesWithin.push_back(edge);
271  (*j)->setIsInnerEdge();
272  ++j; //j = myIncomingEdges.erase(j);
273  continue;
274  }
275  }
276  }
277  ++j;
278  }
279 }
280 
281 
282 void
284  if (myControlledLinks.size() == 0) {
285  // maybe we only loaded a different program for a default traffic light.
286  // Try to build links now.
287  myOriginalNodes.insert(myControlledNodes.begin(), myControlledNodes.end());
288  collectAllLinks();
289  }
290 }
291 
292 
294 void
296  // avoid shifting twice if the edge is incoming and outgoing to a joined TLS
297  if (myShifted.count(edge) == 0) {
299  myShifted.insert(edge);
300  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
301  (*it).shiftLaneIndex(edge, offset);
302  }
303  }
304 }
305 
306 void
308  // XXX what to do if crossings are removed during network building?
309  const unsigned int size = myTLLogic->getNumLinks();
310  unsigned int noLinksAll = 0;
311  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
312  const NBConnection& c = *it;
314  noLinksAll = MAX2(noLinksAll, (unsigned int)c.getTLIndex() + 1);
315  }
316  }
317  int oldCrossings = 0;
318  // collect crossings
319  std::vector<NBNode::Crossing> crossings;
320  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
321  const std::vector<NBNode::Crossing>& c = (*i)->getCrossings();
322  // set tl indices for crossings
323  (*i)->setCrossingTLIndices(noLinksAll);
324  copy(c.begin(), c.end(), std::back_inserter(crossings));
325  noLinksAll += (unsigned int)c.size();
326  oldCrossings += (*i)->numCrossingsFromSumoNet();
327  }
328  const int newCrossings = (int)crossings.size() - oldCrossings;
329  if (newCrossings > 0) {
330  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
331  if (phases.size() > 0) {
332  if (phases.front().state.size() == noLinksAll - newCrossings) {
333  // patch states for the newly added crossings
334 
335  // collect edges
336  assert(size > 0);
337  EdgeVector fromEdges(size, 0);
338  EdgeVector toEdges(size, 0);
339  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
340  const NBConnection& c = *it;
342  if (c.getTLIndex() >= (int)size) {
343  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
344  "' with " + toString(size) + " links.");
345  }
346 
347 
348  fromEdges[c.getTLIndex()] = c.getFrom();
349  toEdges[c.getTLIndex()] = c.getTo();
350  }
351  }
352  const std::string crossingDefaultState(newCrossings, 'r');
353 
354  // rebuild the logic (see NBOwnTLDef.cpp::myCompute)
355  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
357  //std::cout << "patchIfCrossingsAdded for " << getID() << " numPhases=" << phases.size() << "\n";
358  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
359  NBOwnTLDef::addPedestrianPhases(newLogic, it->duration, it->state + crossingDefaultState, crossings, fromEdges, toEdges);
360  }
361  delete myTLLogic;
362  myTLLogic = newLogic;
363  } else if (phases.front().state.size() != noLinksAll) {
364  WRITE_WARNING("Could not patch tlLogic " + getID() + "for new crossings");
365  }
366  }
367  }
368 }
369 
370 
371 /****************************************************************************/
372 
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:1900
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
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.
void closeBuilding()
closes the building process
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.
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:79
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.
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:65
virtual void collectEdges()
Build the list of participating edges.
static const int InvalidTlIndex
Definition: NBConnection.h:124
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.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
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:463
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:53
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.
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.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:369
unsigned int getNumLinks()
Returns the number of participating links.
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)
~NBLoadedSUMOTLDef()
Destructor.
void setType(TrafficLightType type)
Sets the algorithm type of this tls.
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.
NBTrafficLightLogic * myCompute(const NBEdgeCont &ec, unsigned int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
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
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:361