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.sourceforge.net/
13 // Copyright (C) 2001-2013 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 
59 
60 NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
61  TrafficLightType type) :
62  NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type) {}
63 
64 
65 NBOwnTLDef::NBOwnTLDef(const std::string& id, SUMOTime offset,
66  TrafficLightType type) :
67  NBTrafficLightDefinition(id, DefaultProgramID, offset, type) {}
68 
69 
71 
72 
73 int
74 NBOwnTLDef::getToPrio(const NBEdge* const e) {
75  return e->getJunctionPriority(e->getToNode());
76 }
77 
78 
81  switch (dir) {
82  case LINKDIR_STRAIGHT:
83  case LINKDIR_PARTLEFT:
84  case LINKDIR_PARTRIGHT:
85  return 2.;
86  case LINKDIR_LEFT:
87  case LINKDIR_RIGHT:
88  return .5;
89  case LINKDIR_NODIR:
90  case LINKDIR_TURN:
91  return 0;
92  }
93  return 0;
94 }
95 
98  SUMOReal val = 0;
99  for (unsigned int e1l = 0; e1l < e1->getNumLanes(); e1l++) {
100  std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
101  for (unsigned int e2l = 0; e2l < e2->getNumLanes(); e2l++) {
102  std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
103  for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
104  if (e1->getTurnDestination() == (*e1c).toEdge) {
105  continue;
106  }
107  for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
108  if (e2->getTurnDestination() == (*e2c).toEdge) {
109  continue;
110  }
111  if (!foes(e1, (*e1c).toEdge, e2, (*e2c).toEdge)) {
112  val += getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
113  val += getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
114  }
115  }
116  }
117  }
118  }
119  return val;
120 }
121 
122 
123 std::pair<NBEdge*, NBEdge*>
125  std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
126  SUMOReal bestValue = -1;
127  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
128  for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
129  const SUMOReal value = computeUnblockedWeightedStreamNumber(*i, *j);
130  if (value > bestValue) {
131  bestValue = value;
132  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
133  } else if (value == bestValue) {
134  const SUMOReal ca = GeomHelper::getMinAngleDiff((*i)->getAngleAtNode((*i)->getToNode()), (*j)->getAngleAtNode((*j)->getToNode()));
135  const SUMOReal oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
136  if (fabs(oa - ca) < NUMERICAL_EPS) { // break ties by id
137  if (bestPair.first->getID() < (*i)->getID()) {
138  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
139  }
140  } else if (oa < ca) {
141  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
142  }
143  }
144  }
145  }
146  return bestPair;
147 }
148 
149 
150 std::pair<NBEdge*, NBEdge*>
152  if (incoming.size() == 1) {
153  // only one there - return the one
154  std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(0));
155  incoming.clear();
156  return ret;
157  }
158  // determine the best combination
159  // by priority, first
160  EdgeVector used;
161  std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
162  used.push_back(*incoming.begin()); // the first will definitely be used
163  // get the ones with the same priority
164  int prio = getToPrio(*used.begin());
165  for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio != getToPrio(*i); ++i) {
166  used.push_back(*i);
167  }
168  // if there only lower priorised, use these, too
169  if (used.size() < 2) {
170  used = incoming;
171  }
172  std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
173  incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
174  incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
175  return ret;
176 }
177 
178 
181  unsigned int brakingTimeSeconds) {
182  const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
183  const SUMOTime leftTurnTime = TIME2STEPS(6); // make configurable ?
184  // build complete lists first
185  const EdgeVector& incoming = getIncomingEdges();
186  EdgeVector fromEdges, toEdges;
187  std::vector<bool> isLeftMoverV, isTurnaround;
188  unsigned int noLanesAll = 0;
189  unsigned int noLinksAll = 0;
190  for (unsigned int i1 = 0; i1 < incoming.size(); i1++) {
191  unsigned int noLanes = incoming[i1]->getNumLanes();
192  noLanesAll += noLanes;
193  for (unsigned int i2 = 0; i2 < noLanes; i2++) {
194  NBEdge* fromEdge = incoming[i1];
195  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
196  noLinksAll += (unsigned int) approached.size();
197  for (unsigned int i3 = 0; i3 < approached.size(); i3++) {
198  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
199  --noLinksAll;
200  continue;
201  }
202  assert(i3 < approached.size());
203  NBEdge* toEdge = approached[i3].toEdge;
204  fromEdges.push_back(fromEdge);
205  //myFromLanes.push_back(i2);
206  toEdges.push_back(toEdge);
207  if (toEdge != 0) {
208  isLeftMoverV.push_back(
209  isLeftMover(fromEdge, toEdge)
210  ||
211  fromEdge->isTurningDirectionAt(fromEdge->getToNode(), toEdge));
212 
213  isTurnaround.push_back(
214  fromEdge->isTurningDirectionAt(
215  fromEdge->getToNode(), toEdge));
216  } else {
217  isLeftMoverV.push_back(true);
218  isTurnaround.push_back(true);
219  }
220  }
221  }
222  }
223 
224  NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType);
225  EdgeVector toProc = incoming;
226  const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
227  // build all phases
228  while (toProc.size() > 0) {
229  std::pair<NBEdge*, NBEdge*> chosen;
230  if (incoming.size() == 2) {
231  chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
232  toProc.erase(toProc.begin());
233  } else {
234  chosen = getBestPair(toProc);
235  }
236  unsigned int pos = 0;
237  std::string state((size_t) noLinksAll, 'o');
238  // plain straight movers
239  for (unsigned int i1 = 0; i1 < (unsigned int) incoming.size(); ++i1) {
240  NBEdge* fromEdge = incoming[i1];
241  const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
242  const unsigned int numLanes = fromEdge->getNumLanes();
243  for (unsigned int i2 = 0; i2 < numLanes; i2++) {
244  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
245  for (unsigned int i3 = 0; i3 < approached.size(); ++i3) {
246  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
247  continue;
248  }
249  if (inChosen) {
250  state[pos] = 'G';
251  } else {
252  state[pos] = 'r';
253  }
254  ++pos;
255  }
256  }
257  }
258  // correct behaviour for those that are not in chosen, but may drive, though
259  for (unsigned int i1 = 0; i1 < pos; ++i1) {
260  if (state[i1] == 'G') {
261  continue;
262  }
263  bool isForbidden = false;
264  for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) {
265  if (state[i2] == 'G' && !isTurnaround[i2] &&
266  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
267  isForbidden = true;
268  }
269  }
270  if (!isForbidden) {
271  state[i1] = 'G';
272  }
273  }
274  // correct behaviour for those that have to wait (mainly left-mover)
275  bool haveForbiddenLeftMover = false;
276  for (unsigned int i1 = 0; i1 < pos; ++i1) {
277  if (state[i1] != 'G') {
278  continue;
279  }
280  for (unsigned int i2 = 0; i2 < pos; ++i2) {
281  if ((state[i2] == 'G' || state[i2] == 'g') && forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true)) {
282  state[i1] = 'g';
283  if (!isTurnaround[i1]) {
284  haveForbiddenLeftMover = true;
285  }
286  }
287  }
288  }
289  // add step
290  logic->addStep(greenTime, state);
291 
292  if (brakingTime > 0) {
293  // build yellow (straight)
294  for (unsigned int i1 = 0; i1 < pos; ++i1) {
295  if (state[i1] != 'G' && state[i1] != 'g') {
296  continue;
297  }
298  if ((state[i1] >= 'a' && state[i1] <= 'z') && haveForbiddenLeftMover) {
299  continue;
300  }
301  state[i1] = 'y';
302  }
303  // add step
304  logic->addStep(brakingTime, state);
305  }
306 
307  if (haveForbiddenLeftMover) {
308  // build left green
309  for (unsigned int i1 = 0; i1 < pos; ++i1) {
310  if (state[i1] == 'Y' || state[i1] == 'y') {
311  state[i1] = 'r';
312  continue;
313  }
314  if (state[i1] == 'g') {
315  state[i1] = 'G';
316  }
317  }
318  // add step
319  logic->addStep(leftTurnTime, state);
320 
321  // build left yellow
322  if (brakingTime > 0) {
323  for (unsigned int i1 = 0; i1 < pos; ++i1) {
324  if (state[i1] != 'G' && state[i1] != 'g') {
325  continue;
326  }
327  state[i1] = 'y';
328  }
329  // add step
330  logic->addStep(brakingTime, state);
331  }
332  }
333  }
334  const SUMOTime totalDuration = logic->getDuration();
335  if (totalDuration > 0) {
336  if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
337  WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + ".");
338  }
339  return logic;
340  } else {
341  delete logic;
342  return 0;
343  }
344 }
345 
346 
347 void
349 
350 
351 void
353  collectAllLinks();
354 }
355 
356 
357 void
359  // assign participating nodes to the request
360  collectNodes();
361  // collect the information about participating edges and links
362  collectEdges();
363  collectLinks();
364 }
365 
366 
367 void
369  // set the information about the link's positions within the tl into the
370  // edges the links are starting at, respectively
371  for (NBConnectionVector::const_iterator j = myControlledLinks.begin(); j != myControlledLinks.end(); ++j) {
372  const NBConnection& conn = *j;
373  NBEdge* edge = conn.getFrom();
374  edge->setControllingTLInformation(conn, getID());
375  }
376 }
377 
378 
379 void
380 NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
381  const EdgeVector& /*outgoing*/) {}
382 
383 
384 void
385 NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
386  NBEdge* /*by*/, int /*byLane*/) {}
387 
388 
389 
390 /****************************************************************************/