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