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-2017 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 // ===========================================================================
47 // method definitions
48 // ===========================================================================
49 
50 NBLoadedSUMOTLDef::NBLoadedSUMOTLDef(const std::string& id, const std::string& programID,
51  SUMOTime offset, TrafficLightType type) :
52  NBTrafficLightDefinition(id, programID, offset, type),
53  myTLLogic(0) {
54  myTLLogic = new NBTrafficLightLogic(id, programID, 0, offset, type);
55 }
56 
57 
59  // allow for adding a new program for the same def: take the programID from the new logic
60  NBTrafficLightDefinition(def->getID(), logic->getProgramID(), def->getOffset(), def->getType()),
61  myTLLogic(new NBTrafficLightLogic(logic)),
62  myOriginalNodes(def->getNodes().begin(), def->getNodes().end()) {
63  assert(def->getOffset() == logic->getOffset());
64  assert(def->getType() == logic->getType());
66  myControlledNodes = def->getNodes();
67 }
68 
69 
71  delete myTLLogic;
72 }
73 
74 
76 NBLoadedSUMOTLDef::myCompute(int brakingTimeSeconds) {
77  // @todo what to do with those parameters?
78  UNUSED_PARAMETER(brakingTimeSeconds);
81  return new NBTrafficLightLogic(myTLLogic);
82 }
83 
84 
85 void
86 NBLoadedSUMOTLDef::addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex) {
87  assert(myTLLogic->getNumLinks() > 0); // logic should be loaded by now
88  if (linkIndex >= (int)myTLLogic->getNumLinks()) {
89  throw ProcessError("Invalid linkIndex " + toString(linkIndex) + " for traffic light '" + getID() +
90  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
91  }
92  NBConnection conn(from, fromLane, to, toLane, linkIndex);
93  // avoid duplicates
94  remove_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(conn));
95  myControlledLinks.push_back(conn);
96  addNode(from->getToNode());
97  addNode(to->getFromNode());
98  myOriginalNodes.insert(from->getToNode());
99  myOriginalNodes.insert(to->getFromNode());
100  // added connections are definitely controlled. make sure none are removed because they lie within the tl
101  // myControlledInnerEdges.insert(from->getID()); // @todo recheck: this appears to be obsolete
102  // set this information now so that it can be used while loading diffs
103  from->setControllingTLInformation(conn, getID());
104 }
105 
106 
107 void
109  // if nodes have been removed our links may have been invalidated as well
110  // since no logic will be built anyway there is no reason to inform any edges
111  if (amInvalid()) {
112  return;
113  }
114  // set the information about the link's positions within the tl into the
115  // edges the links are starting at, respectively
116  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
117  const NBConnection& c = *it;
118  if (c.getTLIndex() >= (int)myTLLogic->getNumLinks()) {
119  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
120  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
121  }
122  NBEdge* edge = c.getFrom();
123  if (edge != 0) {
125  }
126  }
127 }
128 
129 
130 void
132 
133 
134 void
135 NBLoadedSUMOTLDef::replaceRemoved(NBEdge* removed, int removedLane, NBEdge* by, int byLane) {
136  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
137  (*it).replaceFrom(removed, removedLane, by, byLane);
138  (*it).replaceTo(removed, removedLane, by, byLane);
139  }
140 }
141 
142 
143 void
144 NBLoadedSUMOTLDef::addPhase(SUMOTime duration, const std::string& state) {
145  myTLLogic->addStep(duration, state);
146 }
147 
148 
149 bool
151  if (myControlledLinks.size() == 0) {
152  return true;
153  }
154  // make sure that myControlledNodes are the original nodes
155  if (myControlledNodes.size() != myOriginalNodes.size()) {
156  return true;
157  }
158  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
159  if (myOriginalNodes.count(*i) != 1) {
160  return true;
161  }
162  }
163  return false;
164 }
165 
166 
167 void
168 NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
169  NBConnectionVector::iterator it = myControlledLinks.begin();
170  // find the connection but ignore its TLIndex since it might have been
171  // invalidated by an earlier removal
172  for (; it != myControlledLinks.end(); ++it) {
173  if (it->getFrom() == conn.getFrom() &&
174  it->getTo() == conn.getTo() &&
175  it->getFromLane() == conn.getFromLane() &&
176  it->getToLane() == conn.getToLane()) {
177  break;
178  }
179  }
180  if (it == myControlledLinks.end()) {
181  // a traffic light doesn't always controll all connections at a junction
182  // especially when using the option --tls.join
183  return;
184  }
185  const int removed = it->getTLIndex();
186  // remove the connection
187  myControlledLinks.erase(it);
188  if (reconstruct) {
189  // updating the edge is only needed for immediate use in NETEDIT.
190  // It may conflict with loading diffs
191  conn.getFrom()->setControllingTLInformation(conn, "");
192  // shift link numbers down so there is no gap
193  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
194  NBConnection& c = *it;
195  if (c.getTLIndex() > removed) {
196  c.setTLIndex(c.getTLIndex() - 1);
197  }
198  }
199  // update controlling information with new link numbers
201  // rebuild the logic
202  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
204  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
205  std::string newState = it->state;
206  newState.erase(newState.begin() + removed);
207  newLogic->addStep(it->duration, newState);
208  }
209  delete myTLLogic;
210  myTLLogic = newLogic;
211  }
212 }
213 
214 
215 void
217  myOffset = offset;
218  myTLLogic->setOffset(offset);
219 }
220 
221 
222 void
224  myType = type;
225  myTLLogic->setType(type);
226 }
227 
228 
229 void
231  if (myControlledLinks.size() == 0) {
233  }
234  myIncomingEdges.clear();
235  EdgeVector myOutgoing;
236  // collect the edges from the participating nodes
237  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
238  const EdgeVector& incoming = (*i)->getIncomingEdges();
239  copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
240  const EdgeVector& outgoing = (*i)->getOutgoingEdges();
241  copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
242  }
243  // check which of the edges are completely within the junction
244  // and which are uncontrolled as well (we already know myControlledLinks)
245  for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) {
246  NBEdge* edge = *j;
247  // an edge lies within the logic if it is outgoing as well as incoming
248  EdgeVector::iterator k = find(myOutgoing.begin(), myOutgoing.end(), edge);
249  if (k != myOutgoing.end()) {
250  if (myControlledInnerEdges.count(edge->getID()) == 0) {
251  bool controlled = false;
252  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
253  if ((*it).getFrom() == edge) {
254  controlled = true;
255  break;
256  }
257  }
258  if (controlled) {
259  myControlledInnerEdges.insert(edge->getID());
260  } else {
261  myEdgesWithin.push_back(edge);
262  (*j)->setIsInnerEdge();
263  ++j; //j = myIncomingEdges.erase(j);
264  continue;
265  }
266  }
267  }
268  ++j;
269  }
270 }
271 
272 
273 void
275  if (myControlledLinks.size() == 0) {
276  // maybe we only loaded a different program for a default traffic light.
277  // Try to build links now.
278  myOriginalNodes.insert(myControlledNodes.begin(), myControlledNodes.end());
279  collectAllLinks();
280  }
281 }
282 
283 
285 void
287  // avoid shifting twice if the edge is incoming and outgoing to a joined TLS
288  if (myShifted.count(edge) == 0) {
290  myShifted.insert(edge);
291  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
292  (*it).shiftLaneIndex(edge, offset);
293  }
294  }
295 }
296 
297 void
299  // XXX what to do if crossings are removed during network building?
300  const int size = myTLLogic->getNumLinks();
301  int noLinksAll = 0;
302  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
303  const NBConnection& c = *it;
305  noLinksAll = MAX2(noLinksAll, (int)c.getTLIndex() + 1);
306  }
307  }
308  int oldCrossings = 0;
309  // collect crossings
310  std::vector<NBNode::Crossing> crossings;
311  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
312  const std::vector<NBNode::Crossing>& c = (*i)->getCrossings();
313  // set tl indices for crossings
314  (*i)->setCrossingTLIndices(getID(), noLinksAll);
315  copy(c.begin(), c.end(), std::back_inserter(crossings));
316  noLinksAll += (int)c.size();
317  oldCrossings += (*i)->numCrossingsFromSumoNet();
318  }
319  const int newCrossings = (int)crossings.size() - oldCrossings;
320  if (newCrossings > 0) {
321  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
322  if (phases.size() > 0) {
323  if ((int)phases.front().state.size() == noLinksAll - newCrossings) {
324  // patch states for the newly added crossings
325 
326  // collect edges
327  EdgeVector fromEdges(size, (NBEdge*)0);
328  EdgeVector toEdges(size, (NBEdge*)0);
329  std::vector<int> fromLanes(size, 0);
330  collectEdgeVectors(fromEdges, toEdges, fromLanes);
331  const std::string crossingDefaultState(newCrossings, 'r');
332 
333  // rebuild the logic (see NBOwnTLDef.cpp::myCompute)
334  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
336  SUMOTime brakingTime = TIME2STEPS(3);
337  //std::cout << "patchIfCrossingsAdded for " << getID() << " numPhases=" << phases.size() << "\n";
338  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
339  if ((*it).state.find_first_of("yY") != std::string::npos) {
340  brakingTime = MAX2(brakingTime, it->duration);
341  }
342  NBOwnTLDef::addPedestrianPhases(newLogic, it->duration, it->state + crossingDefaultState, crossings, fromEdges, toEdges);
343  }
344  NBOwnTLDef::addPedestrianScramble(newLogic, noLinksAll, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
345 
346  delete myTLLogic;
347  myTLLogic = newLogic;
348  } else if ((int)phases.front().state.size() != noLinksAll) {
349  WRITE_WARNING("Could not patch tlLogic " + getID() + "for new crossings");
350  }
351  }
352  }
353 }
354 
355 
356 void
357 NBLoadedSUMOTLDef::collectEdgeVectors(EdgeVector& fromEdges, EdgeVector& toEdges, std::vector<int>& fromLanes) const {
358  assert(fromEdges.size() > 0);
359  assert(fromEdges.size() == toEdges.size());
360  const int size = (int)fromEdges.size();
361 
362  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
363  const NBConnection& c = *it;
365  if (c.getTLIndex() >= size) {
366  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
367  "' with " + toString(size) + " links.");
368  }
369  fromEdges[c.getTLIndex()] = c.getFrom();
370  toEdges[c.getTLIndex()] = c.getTo();
371  fromLanes[c.getTLIndex()] = c.getFromLane();
372  }
373  }
374 }
375 
376 
377 void
379  if (!amInvalid() && !myNeedsContRelationReady) {
380  myNeedsContRelation.clear();
381  myRightOnRedConflicts.clear();
382  const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
383  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
384  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
385  const std::string state = (*it).state;
386  for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
387  const NBConnection& c1 = *it1;
388  const int i1 = c1.getTLIndex();
389  if (i1 == NBConnection::InvalidTlIndex || (state[i1] != 'g' && state[i1] != 's') || c1.getFrom() == 0 || c1.getTo() == 0) {
390  continue;
391  }
392  for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
393  const NBConnection& c2 = *it2;
394  const int i2 = c2.getTLIndex();
396  && i2 != i1
397  && (state[i2] == 'G' || state[i2] == 'g')
398  && c2.getFrom() != 0 && c2.getTo() != 0) {
399  const bool rightTurnConflict = NBNode::rightTurnConflict(
400  c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
401  const bool forbidden = forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin);
402  const bool isFoes = foes(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo()) && !c2.getFrom()->isTurningDirectionAt(c2.getTo());
403  if (forbidden || rightTurnConflict) {
404  myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
405  }
406  if (isFoes) {
407  myRightOnRedConflicts.insert(std::make_pair(i1, i2));
408  }
409  //std::cout << getID() << " i1=" << i1 << " i2=" << i2 << " rightTurnConflict=" << rightTurnConflict << " forbidden=" << forbidden << " isFoes=" << isFoes << "\n";
410  }
411  }
412  }
413  }
414  }
417 }
418 
419 
420 bool
421 NBLoadedSUMOTLDef::rightOnRedConflict(int index, int foeIndex) const {
422  if (amInvalid()) {
423  return false;
424  }
428  }
429  return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
430 }
431 
432 
433 /****************************************************************************/
434 
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:2431
TrafficLightType myType
The algorithm type for the traffic light.
SUMOTime getOffset() const
Returns the offset of first switch.
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.
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.
EdgeVector myIncomingEdges
The list of incoming edges.
The representation of a single edge during network building.
Definition: NBEdge.h:71
TrafficLightType getType() const
get the algorithm type (static etc..)
class for identifying connections
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
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:70
NBEdge * getFrom() const
returns the from-edge (start of the connection)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
SUMOTime myOffset
The offset in the program.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
#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:65
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:1385
void setTLIndex(int tlIndex)
Definition: NBConnection.h:105
SUMOTime getOffset()
Returns the offset.
void setType(TrafficLightType type)
set the algorithm type (static etc..)
void initNeedsContRelation() const
virtual void collectEdges()
Build the list of participating edges.
static const int InvalidTlIndex
Definition: NBConnection.h:126
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
std::set< std::string > myControlledInnerEdges
Set of inner edges that shall be controlled, though.
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.
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
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:437
const std::string & getProgramID() const
Returns the ProgramID.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
int getToLane() const
returns the to-lane
NBEdge * getTo() const
returns the to-edge (end of the connection)
std::set< NBEdge * > myShifted
set of edges with shifted lane indices (to avoid shifting twice)
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:658
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 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...
TrafficLightType getType() const
get the algorithm type (static etc..)
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
void collectLinks()
Collects the links participating in this traffic light (only if not previously loaded) ...
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2367
int getFromLane() const
returns the from-lane
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
~NBLoadedSUMOTLDef()
Destructor.
long long int SUMOTime
Definition: TraCIDefs.h:52
data structure for caching needsCont information
void setType(TrafficLightType type)
Sets the algorithm type of this tls.
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled ...
Definition: NBConnection.h:100
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:427
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
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.
NBConnectionVector myControlledLinks
The list of controlled links.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:434
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
void collectEdgeVectors(EdgeVector &fromEdges, EdgeVector &toEdges, std::vector< int > &fromLanes) const
Collects the edges for each tlIndex.