SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NBOwnTLDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A traffic light logics which must be computed (only nodes/edges are given)
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo-sim.org/
13 // Copyright (C) 2001-2014 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 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <vector>
35 #include <cassert>
37 #include "NBNode.h"
38 #include "NBOwnTLDef.h"
39 #include "NBTrafficLightLogic.h"
42 #include <utils/common/ToString.h>
44 #include <utils/options/Option.h>
45 
46 #ifdef CHECK_MEMORY_LEAKS
47 #include <foreign/nvwa/debug_new.h>
48 #endif // CHECK_MEMORY_LEAKS
49 
50 
51 // ===========================================================================
52 // member method definitions
53 // ===========================================================================
54 NBOwnTLDef::NBOwnTLDef(const std::string& id,
55  const std::vector<NBNode*>& junctions, SUMOTime offset,
56  TrafficLightType type) :
57  NBTrafficLightDefinition(id, junctions, DefaultProgramID, offset, type),
58  myHaveSinglePhase(false)
59 {}
60 
61 
62 NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
63  TrafficLightType type) :
64  NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type),
65  myHaveSinglePhase(false)
66 {}
67 
68 
69 NBOwnTLDef::NBOwnTLDef(const std::string& id, SUMOTime offset,
70  TrafficLightType type) :
71  NBTrafficLightDefinition(id, DefaultProgramID, offset, type),
72  myHaveSinglePhase(false)
73 {}
74 
75 
77 
78 
79 int
80 NBOwnTLDef::getToPrio(const NBEdge* const e) {
81  return e->getJunctionPriority(e->getToNode());
82 }
83 
84 
87  switch (dir) {
88  case LINKDIR_STRAIGHT:
89  case LINKDIR_PARTLEFT:
90  case LINKDIR_PARTRIGHT:
91  return 2.;
92  case LINKDIR_LEFT:
93  case LINKDIR_RIGHT:
94  return .5;
95  case LINKDIR_NODIR:
96  case LINKDIR_TURN:
97  return 0;
98  }
99  return 0;
100 }
101 
102 SUMOReal
104  SUMOReal val = 0;
105  for (unsigned int e1l = 0; e1l < e1->getNumLanes(); e1l++) {
106  std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
107  for (unsigned int e2l = 0; e2l < e2->getNumLanes(); e2l++) {
108  std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
109  for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
110  if (e1->getTurnDestination() == (*e1c).toEdge) {
111  continue;
112  }
113  for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
114  if (e2->getTurnDestination() == (*e2c).toEdge) {
115  continue;
116  }
117  if (!foes(e1, (*e1c).toEdge, e2, (*e2c).toEdge)) {
118  val += getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
119  val += getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
120  }
121  }
122  }
123  }
124  }
125  return val;
126 }
127 
128 
129 std::pair<NBEdge*, NBEdge*>
131  std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
132  SUMOReal bestValue = -1;
133  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
134  for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
135  const SUMOReal value = computeUnblockedWeightedStreamNumber(*i, *j);
136  if (value > bestValue) {
137  bestValue = value;
138  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
139  } else if (value == bestValue) {
140  const SUMOReal ca = GeomHelper::getMinAngleDiff((*i)->getAngleAtNode((*i)->getToNode()), (*j)->getAngleAtNode((*j)->getToNode()));
141  const SUMOReal oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
142  if (fabs(oa - ca) < NUMERICAL_EPS) { // break ties by id
143  if (bestPair.first->getID() < (*i)->getID()) {
144  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
145  }
146  } else if (oa < ca) {
147  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
148  }
149  }
150  }
151  }
152  return bestPair;
153 }
154 
155 
156 std::pair<NBEdge*, NBEdge*>
158  if (incoming.size() == 1) {
159  // only one there - return the one
160  std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(0));
161  incoming.clear();
162  return ret;
163  }
164  // determine the best combination
165  // by priority, first
166  EdgeVector used;
167  std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
168  used.push_back(*incoming.begin()); // the first will definitely be used
169  // get the ones with the same priority
170  int prio = getToPrio(*used.begin());
171  for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio != getToPrio(*i); ++i) {
172  used.push_back(*i);
173  }
174  // if there only lower priorised, use these, too
175  if (used.size() < 2) {
176  used = incoming;
177  }
178  std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
179  incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
180  incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
181  return ret;
182 }
183 
184 
187  unsigned int brakingTimeSeconds) {
188  const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
189  const SUMOTime leftTurnTime = TIME2STEPS(6); // make configurable ?
190  // build complete lists first
191  const EdgeVector& incoming = getIncomingEdges();
192  EdgeVector fromEdges, toEdges;
193  std::vector<bool> isLeftMoverV, isTurnaround;
194  unsigned int noLanesAll = 0;
195  unsigned int noLinksAll = 0;
196  for (unsigned int i1 = 0; i1 < incoming.size(); i1++) {
197  unsigned int noLanes = incoming[i1]->getNumLanes();
198  noLanesAll += noLanes;
199  for (unsigned int i2 = 0; i2 < noLanes; i2++) {
200  NBEdge* fromEdge = incoming[i1];
201  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
202  noLinksAll += (unsigned int) approached.size();
203  for (unsigned int i3 = 0; i3 < approached.size(); i3++) {
204  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
205  --noLinksAll;
206  continue;
207  }
208  assert(i3 < approached.size());
209  NBEdge* toEdge = approached[i3].toEdge;
210  fromEdges.push_back(fromEdge);
211  //myFromLanes.push_back(i2);
212  toEdges.push_back(toEdge);
213  if (toEdge != 0) {
214  isLeftMoverV.push_back(
215  isLeftMover(fromEdge, toEdge)
216  ||
217  fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));
218 
219  isTurnaround.push_back(
220  fromEdge->isTurningDirectionAt(
221  fromEdge->getToNode(), toEdge));
222  } else {
223  isLeftMoverV.push_back(true);
224  isTurnaround.push_back(true);
225  }
226  }
227  }
228  }
229 
230  NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType);
231  EdgeVector toProc = incoming;
232  const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
233  // build all phases
234  while (toProc.size() > 0) {
235  std::pair<NBEdge*, NBEdge*> chosen;
236  if (incoming.size() == 2) {
237  chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
238  toProc.erase(toProc.begin());
239  } else {
240  chosen = getBestPair(toProc);
241  }
242  unsigned int pos = 0;
243  std::string state((size_t) noLinksAll, 'o');
244  // plain straight movers
245  for (unsigned int i1 = 0; i1 < (unsigned int) incoming.size(); ++i1) {
246  NBEdge* fromEdge = incoming[i1];
247  const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
248  const unsigned int numLanes = fromEdge->getNumLanes();
249  for (unsigned int i2 = 0; i2 < numLanes; i2++) {
250  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
251  for (unsigned int i3 = 0; i3 < approached.size(); ++i3) {
252  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
253  continue;
254  }
255  if (inChosen) {
256  state[pos] = 'G';
257  } else {
258  state[pos] = 'r';
259  }
260  ++pos;
261  }
262  }
263  }
264  // correct behaviour for those that are not in chosen, but may drive, though
265  for (unsigned int i1 = 0; i1 < pos; ++i1) {
266  if (state[i1] == 'G') {
267  continue;
268  }
269  bool isForbidden = false;
270  for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) {
271  if (state[i2] == 'G' && !isTurnaround[i2] &&
272  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
273  isForbidden = true;
274  }
275  }
276  if (!isForbidden) {
277  state[i1] = 'G';
278  }
279  }
280  // correct behaviour for those that have to wait (mainly left-mover)
281  bool haveForbiddenLeftMover = false;
282  for (unsigned int i1 = 0; i1 < pos; ++i1) {
283  if (state[i1] != 'G') {
284  continue;
285  }
286  for (unsigned int i2 = 0; i2 < pos; ++i2) {
287  if ((state[i2] == 'G' || state[i2] == 'g') && forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
288  state[i1] = 'g';
289  if (!isTurnaround[i1]) {
290  haveForbiddenLeftMover = true;
291  }
292  }
293  }
294  }
295  // add step
296  logic->addStep(greenTime, state);
297 
298  if (brakingTime > 0) {
299  // build yellow (straight)
300  for (unsigned int i1 = 0; i1 < pos; ++i1) {
301  if (state[i1] != 'G' && state[i1] != 'g') {
302  continue;
303  }
304  if ((state[i1] >= 'a' && state[i1] <= 'z') && haveForbiddenLeftMover) {
305  continue;
306  }
307  state[i1] = 'y';
308  }
309  // add step
310  logic->addStep(brakingTime, state);
311  }
312 
313  if (haveForbiddenLeftMover && !myHaveSinglePhase) {
314  // build left green
315  for (unsigned int i1 = 0; i1 < pos; ++i1) {
316  if (state[i1] == 'Y' || state[i1] == 'y') {
317  state[i1] = 'r';
318  continue;
319  }
320  if (state[i1] == 'g') {
321  state[i1] = 'G';
322  }
323  }
324  // add step
325  logic->addStep(leftTurnTime, state);
326 
327  // build left yellow
328  if (brakingTime > 0) {
329  for (unsigned int i1 = 0; i1 < pos; ++i1) {
330  if (state[i1] != 'G' && state[i1] != 'g') {
331  continue;
332  }
333  state[i1] = 'y';
334  }
335  // add step
336  logic->addStep(brakingTime, state);
337  }
338  }
339  }
340  const SUMOTime totalDuration = logic->getDuration();
341  if (totalDuration > 0) {
342  if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
343  WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + ".");
344  }
345  return logic;
346  } else {
347  delete logic;
348  return 0;
349  }
350 }
351 
352 
353 void
355 
356 
357 void
359  collectAllLinks();
360 }
361 
362 
363 void
365  // assign participating nodes to the request
366  collectNodes();
367  // collect the information about participating edges and links
368  collectEdges();
369  collectLinks();
370 }
371 
372 
373 void
375  // set the information about the link's positions within the tl into the
376  // edges the links are starting at, respectively
377  for (NBConnectionVector::const_iterator j = myControlledLinks.begin(); j != myControlledLinks.end(); ++j) {
378  const NBConnection& conn = *j;
379  NBEdge* edge = conn.getFrom();
380  edge->setControllingTLInformation(conn, getID());
381  }
382 }
383 
384 
385 void
386 NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
387  const EdgeVector& /*outgoing*/) {}
388 
389 
390 void
391 NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
392  NBEdge* /*by*/, int /*byLane*/) {}
393 
394 
395 
396 /****************************************************************************/
The link is a partial left direction.
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:1678
TrafficLightType myType
The algorithm type for the traffic light.
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
A SUMO-compliant built logic for a traffic light.
const std::string & getProgramID() const
Returns the ProgramID.
The representation of a single edge during network building.
Definition: NBEdge.h:71
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
Definition: NBEdge.cpp:1667
The link is a 180 degree turn.
void collectNodes()
Collects the nodes participating in this traffic light.
Definition: NBOwnTLDef.cpp:354
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:61
The base class for traffic light logic definitions.
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
bool isTurningDirectionAt(const NBNode *n, const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1597
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:715
SUMOTime myOffset
The offset in the program.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:196
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
Definition: NBOwnTLDef.cpp:157
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
The link is a straight direction.
const std::string & getID() const
Returns the id.
Definition: Named.h:60
void collectEdges()
Build the list of participating edges.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
Definition: NBOwnTLDef.cpp:391
std::pair< NBEdge *, NBEdge * > getBestCombination(const EdgeVector &edges)
Returns the combination of two edges from the given which has most unblocked streams.
Definition: NBOwnTLDef.cpp:130
bool myHaveSinglePhase
Whether left-mover should not have an additional phase.
Definition: NBOwnTLDef.h:222
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:338
~NBOwnTLDef()
Destructor.
Definition: NBOwnTLDef.cpp:76
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
The link is a (hard) right direction.
The link is a partial right direction.
SUMOTime getDuration() const
Returns the duration of the complete cycle.
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1101
SUMOReal computeUnblockedWeightedStreamNumber(const NBEdge *const e1, const NBEdge *const e2)
Returns how many streams outgoing from the edges can pass the junction without being blocked...
Definition: NBOwnTLDef.cpp:103
NBOwnTLDef(const std::string &id, const std::vector< NBNode * > &junctions, SUMOTime offset, TrafficLightType type)
Constructor.
Definition: NBOwnTLDef.cpp:54
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:362
void setTLControllingInformation(const NBEdgeCont &ec) const
Informs edges about being controlled by a tls.
Definition: NBOwnTLDef.cpp:374
void collectLinks()
Collects the links participating in this traffic light If a link could not be found.
Definition: NBOwnTLDef.cpp:358
SUMOReal getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
Definition: NBOwnTLDef.cpp:86
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:38
NBTrafficLightLogic * myCompute(const NBEdgeCont &ec, unsigned int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
Definition: NBOwnTLDef.cpp:186
static SUMOReal getMinAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:391
Represents a single node (junction) during network building.
Definition: NBNode.h:74
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.
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1889
#define SUMOReal
Definition: config.h:215
#define NUMERICAL_EPS
Definition: config.h:159
bool isLeftMover(const NBEdge *const from, const NBEdge *const to) const
returns the information whether the given link is a left-mover
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
Sorts edges by their priority within the node they end at.
Definition: NBOwnTLDef.h:206
void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
Definition: NBOwnTLDef.cpp:364
NBConnectionVector myControlledLinks
The list of controlled links.
int getToPrio(const NBEdge *const e)
Returns this edge's priority at the node it ends at.
Definition: NBOwnTLDef.cpp:80
TrafficLightType
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
Definition: NBOwnTLDef.cpp:386
The link has no direction (is a dead end link)
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.
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:1182