SUMO - Simulation of Urban MObility
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.dlr.de/
13 // Copyright (C) 2001-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 // ===========================================================================
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>
36 #include <iterator>
38 #include "NBNode.h"
39 #include "NBOwnTLDef.h"
40 #include "NBTrafficLightLogic.h"
43 #include <utils/common/ToString.h>
45 #include <utils/options/Option.h>
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 #define DUMMY_ID "dummy"
52 #define MIN_GREEN_TIME 5
53 
54 // ===========================================================================
55 // member method definitions
56 // ===========================================================================
57 NBOwnTLDef::NBOwnTLDef(const std::string& id,
58  const std::vector<NBNode*>& junctions, SUMOTime offset,
59  TrafficLightType type) :
60  NBTrafficLightDefinition(id, junctions, DefaultProgramID, offset, type),
61  myHaveSinglePhase(false)
62 {}
63 
64 
65 NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
66  TrafficLightType type) :
67  NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type),
68  myHaveSinglePhase(false)
69 {}
70 
71 
72 NBOwnTLDef::NBOwnTLDef(const std::string& id, SUMOTime offset,
73  TrafficLightType type) :
74  NBTrafficLightDefinition(id, DefaultProgramID, offset, type),
75  myHaveSinglePhase(false)
76 {}
77 
78 
80 
81 
82 int
83 NBOwnTLDef::getToPrio(const NBEdge* const e) {
84  return e->getJunctionPriority(e->getToNode());
85 }
86 
87 
90  switch (dir) {
91  case LINKDIR_STRAIGHT:
92  case LINKDIR_PARTLEFT:
93  case LINKDIR_PARTRIGHT:
94  return 2.;
95  case LINKDIR_LEFT:
96  case LINKDIR_RIGHT:
97  return .5;
98  default:
99  break;
100  }
101  return 0;
102 }
103 
104 SUMOReal
106  SUMOReal val = 0;
107  for (unsigned int e1l = 0; e1l < e1->getNumLanes(); e1l++) {
108  std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
109  for (unsigned int e2l = 0; e2l < e2->getNumLanes(); e2l++) {
110  std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
111  for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
112  if (e1->getTurnDestination() == (*e1c).toEdge) {
113  continue;
114  }
115  for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
116  if (e2->getTurnDestination() == (*e2c).toEdge) {
117  continue;
118  }
119  if (!forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge, true)) {
120  val += getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
121  val += getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
122  }
123  }
124  }
125  }
126  }
127  return val;
128 }
129 
130 
131 std::pair<NBEdge*, NBEdge*>
133  std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
134  SUMOReal bestValue = -1;
135  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
136  for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
137  const SUMOReal value = computeUnblockedWeightedStreamNumber(*i, *j);
138  if (value > bestValue) {
139  bestValue = value;
140  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
141  } else if (value == bestValue) {
142  const SUMOReal ca = GeomHelper::getMinAngleDiff((*i)->getAngleAtNode((*i)->getToNode()), (*j)->getAngleAtNode((*j)->getToNode()));
143  const SUMOReal oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
144  if (fabs(oa - ca) < NUMERICAL_EPS) { // break ties by id
145  if (bestPair.first->getID() < (*i)->getID()) {
146  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
147  }
148  } else if (oa < ca) {
149  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
150  }
151  }
152  }
153  }
154  return bestPair;
155 }
156 
157 
158 std::pair<NBEdge*, NBEdge*>
160  if (incoming.size() == 1) {
161  // only one there - return the one
162  std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(0));
163  incoming.clear();
164  return ret;
165  }
166  // determine the best combination
167  // by priority, first
168  EdgeVector used;
169  std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
170  used.push_back(*incoming.begin()); // the first will definitely be used
171  // get the ones with the same priority
172  int prio = getToPrio(*used.begin());
173  for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio == getToPrio(*i); ++i) {
174  used.push_back(*i);
175  }
176  // if there only lower priorised, use these, too
177  if (used.size() < 2) {
178  used = incoming;
179  }
180  std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
181  incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
182  incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
183  return ret;
184 }
185 
187 NBOwnTLDef::myCompute(const NBEdgeCont&, unsigned int brakingTimeSeconds) {
188  return computeLogicAndConts(brakingTimeSeconds);
189 }
190 
192 NBOwnTLDef::computeLogicAndConts(unsigned int brakingTimeSeconds, bool onlyConts) {
193  myNeedsContRelation.clear();
194  myRightOnRedConflicts.clear();
195  const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
196  const SUMOTime leftTurnTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.left-green.time"));
197  // build complete lists first
198  const EdgeVector& incoming = getIncomingEdges();
199  EdgeVector fromEdges, toEdges;
200  std::vector<bool> isTurnaround;
201  std::vector<int> fromLanes;
202  unsigned int noLanesAll = 0;
203  unsigned int noLinksAll = 0;
204  for (unsigned int i1 = 0; i1 < incoming.size(); i1++) {
205  unsigned int noLanes = incoming[i1]->getNumLanes();
206  noLanesAll += noLanes;
207  for (unsigned int i2 = 0; i2 < noLanes; i2++) {
208  NBEdge* fromEdge = incoming[i1];
209  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
210  noLinksAll += (unsigned int) approached.size();
211  for (unsigned int i3 = 0; i3 < approached.size(); i3++) {
212  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
213  --noLinksAll;
214  continue;
215  }
216  assert(i3 < approached.size());
217  NBEdge* toEdge = approached[i3].toEdge;
218  fromEdges.push_back(fromEdge);
219  fromLanes.push_back((int)i2);
220  toEdges.push_back(toEdge);
221  if (toEdge != 0) {
222  isTurnaround.push_back(fromEdge->isTurningDirectionAt(toEdge));
223  } else {
224  isTurnaround.push_back(true);
225  }
226  }
227  }
228  }
229  // collect crossings
230  std::vector<NBNode::Crossing> crossings;
231  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
232  const std::vector<NBNode::Crossing>& c = (*i)->getCrossings();
233  if (!onlyConts) {
234  // set tl indices for crossings
235  (*i)->setCrossingTLIndices(noLinksAll);
236  }
237  copy(c.begin(), c.end(), std::back_inserter(crossings));
238  noLinksAll += (unsigned int)c.size();
239  }
240 
241  NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType);
242  EdgeVector toProc = getConnectedOuterEdges(incoming);
243  const int greenSeconds = OptionsCont::getOptions().getInt("tls.green.time");
244  const SUMOTime greenTime = TIME2STEPS(greenSeconds);
245  // build all phases
246  std::vector<int> greenPhases; // indices of green phases
247  std::vector<bool> hadGreenMajor(noLinksAll, false);
248  while (toProc.size() > 0) {
249  std::pair<NBEdge*, NBEdge*> chosen;
250  if (incoming.size() == 2) {
251  // if there are only 2 incoming edges we need to decide whether they are a crossing or a "continuation"
252  // @node: this heuristic could be extended to also check the number of outgoing edges
253  SUMOReal angle = fabs(NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
254  // angle would be 180 for straight opposing incoming edges
255  if (angle < 135) {
256  chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(0));
257  toProc.erase(toProc.begin());
258  } else {
259  chosen = getBestPair(toProc);
260  }
261  } else {
262  chosen = getBestPair(toProc);
263  }
264  unsigned int pos = 0;
265  std::string state((size_t) noLinksAll, 'r');
266  //std::cout << " computing " << getID() << " prog=" << getProgramID() << " cho1=" << Named::getIDSecure(chosen.first) << " cho2=" << Named::getIDSecure(chosen.second) << " toProc=" << toString(toProc) << "\n";
267  // plain straight movers
268  for (unsigned int i1 = 0; i1 < (unsigned int) incoming.size(); ++i1) {
269  NBEdge* fromEdge = incoming[i1];
270  const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
271  const unsigned int numLanes = fromEdge->getNumLanes();
272  for (unsigned int i2 = 0; i2 < numLanes; i2++) {
273  std::vector<NBEdge::Connection> approached = fromEdge->getConnectionsFromLane(i2);
274  for (unsigned int i3 = 0; i3 < approached.size(); ++i3) {
275  if (!fromEdge->mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
276  continue;
277  }
278  if (inChosen) {
279  state[pos] = 'G';
280  } else {
281  state[pos] = 'r';
282  }
283  ++pos;
284  }
285  }
286  }
287  //std::cout << " state after plain straight movers=" << state << "\n";
288  // correct behaviour for those that are not in chosen, but may drive, though
289  state = allowFollowersOfChosen(state, fromEdges, toEdges);
290  for (unsigned int i1 = 0; i1 < pos; ++i1) {
291  if (state[i1] == 'G') {
292  continue;
293  }
294  bool isForbidden = false;
295  for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) {
296  if (state[i2] == 'G' && !isTurnaround[i2] &&
297  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
298  isForbidden = true;
299  }
300  }
301  if (!isForbidden && !hasCrossing(fromEdges[i1], toEdges[i1], crossings)) {
302  state[i1] = 'G';
303  } else if (fromEdges[i1]->getToNode()->getType() == NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED &&
304  fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) == LINKDIR_RIGHT) {
305  // handle right-on-red conflicts
306  state[i1] = 's';
307  for (unsigned int i2 = 0; i2 < pos; ++i2) {
308  if (state[i2] == 'G' && !isTurnaround[i2] &&
309  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
310  myRightOnRedConflicts.insert(std::make_pair(i1, i2));
311  }
312  }
313  }
314  }
315  //std::cout << " state after finding additional 'G's=" << state << "\n";
316  // correct behaviour for those that have to wait (mainly left-mover)
317  bool haveForbiddenLeftMover = false;
318  std::vector<bool> rightTurnConflicts(pos, false);
319  state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
320  for (unsigned int i1 = 0; i1 < pos; ++i1) {
321  if (state[i1] == 'G') {
322  hadGreenMajor[i1] = true;
323  }
324  }
325  //std::cout << " state after correcting left movers=" << state << "\n";
326  const std::string vehicleState = state; // backup state before pedestrian modifications
327  greenPhases.push_back((int)logic->getPhases().size());
328  state = addPedestrianPhases(logic, greenTime, state, crossings, fromEdges, toEdges);
329  // pedestrians have 'r' from here on
330  for (unsigned int i1 = pos; i1 < pos + crossings.size(); ++i1) {
331  state[i1] = 'r';
332  }
333 
334  if (brakingTime > 0) {
335  // build yellow (straight)
336  for (unsigned int i1 = 0; i1 < pos; ++i1) {
337  if (state[i1] != 'G' && state[i1] != 'g') {
338  continue;
339  }
340  if ((vehicleState[i1] >= 'a' && vehicleState[i1] <= 'z') && haveForbiddenLeftMover && !rightTurnConflicts[i1]) {
341  continue;
342  }
343  state[i1] = 'y';
344  }
345  // add step
346  logic->addStep(brakingTime, state);
347  }
348 
349  if (haveForbiddenLeftMover && !myHaveSinglePhase && leftTurnTime > 0) {
350  // build left green
351  for (unsigned int i1 = 0; i1 < pos; ++i1) {
352  if (state[i1] == 'Y' || state[i1] == 'y') {
353  state[i1] = 'r';
354  continue;
355  }
356  if (state[i1] == 'g') {
357  state[i1] = 'G';
358  }
359  }
360  state = allowFollowersOfChosen(state, fromEdges, toEdges);
361  state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
362 
363  // add step
364  logic->addStep(leftTurnTime, state);
365 
366  // build left yellow
367  if (brakingTime > 0) {
368  for (unsigned int i1 = 0; i1 < pos; ++i1) {
369  if (state[i1] != 'G' && state[i1] != 'g') {
370  continue;
371  }
372  state[i1] = 'y';
373  }
374  // add step
375  logic->addStep(brakingTime, state);
376  }
377  }
378  }
379  // fix pedestrian crossings that did not get the green light yet
380  if (crossings.size() > 0) {
381  const int vehLinks = noLinksAll - (int)crossings.size();
382  std::vector<bool> foundGreen(crossings.size(), false);
383  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->getPhases();
384  for (int i = 0; i < (int)phases.size(); ++i) {
385  const std::string state = phases[i].state;
386  for (int j = 0; j < (int)crossings.size(); ++j) {
387  LinkState ls = (LinkState)state[vehLinks + j];
389  foundGreen[j] = true;
390  }
391  }
392  }
393  for (int j = 0; j < (int)foundGreen.size(); ++j) {
394  if (!foundGreen[j]) {
395  // add a phase where all pedestrians may walk, followed by a clearing phase
396  addPedestrianPhases(logic, TIME2STEPS(10), std::string(noLinksAll, 'r'), crossings, fromEdges, toEdges);
397  break;
398  }
399  }
400  }
401 
402  SUMOTime totalDuration = logic->getDuration();
403  if (OptionsCont::getOptions().isDefault("tls.green.time") || !OptionsCont::getOptions().isDefault("tls.cycle.time")) {
404  // adapt to cycle time by changing the duration of the green phases
405  const SUMOTime cycleTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.cycle.time"));
406  SUMOTime greenPhaseTime = 0;
407  for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
408  greenPhaseTime += logic->getPhases()[*it].duration;
409  }
410  const int patchSeconds = (int)(STEPS2TIME(cycleTime - totalDuration) / greenPhases.size());
411  const int patchSecondsRest = (int)(STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (int)greenPhases.size();
412  //std::cout << "cT=" << cycleTime << " td=" << totalDuration << " pS=" << patchSeconds << " pSR=" << patchSecondsRest << "\n";
413  if (greenSeconds + patchSeconds < MIN_GREEN_TIME || greenSeconds + patchSeconds + patchSecondsRest < MIN_GREEN_TIME) {
414  if (getID() != DUMMY_ID) {
415  WRITE_WARNING("The traffic light '" + getID() + "' cannot be adapted to a cycle time of " + time2string(cycleTime) + ".");
416  }
417  // @todo use a multiple of cycleTime ?
418  } else {
419  for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
420  logic->setPhaseDuration(*it, logic->getPhases()[*it].duration + TIME2STEPS(patchSeconds));
421  }
422  logic->setPhaseDuration(greenPhases.front(), logic->getPhases()[greenPhases.front()].duration + TIME2STEPS(patchSecondsRest));
423  totalDuration = logic->getDuration();
424  }
425  }
426 
428  // this computation only makes sense for single nodes
430  if (totalDuration > 0) {
431  if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
432  WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + ".");
433  }
434  logic->closeBuilding();
435  return logic;
436  } else {
437  delete logic;
438  return 0;
439  }
440 }
441 
442 
443 bool
444 NBOwnTLDef::hasCrossing(const NBEdge* from, const NBEdge* to, const std::vector<NBNode::Crossing>& crossings) {
445  assert(to != 0);
446  for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
447  const NBNode::Crossing& cross = *it;
448  // only check connections at this crossings node
449  if (to->getFromNode() == cross.node) {
450  for (EdgeVector::const_iterator it_e = cross.edges.begin(); it_e != cross.edges.end(); ++it_e) {
451  const NBEdge* edge = *it_e;
452  if (edge == from || edge == to) {
453  return true;
454  }
455  }
456  }
457  }
458  return false;
459 }
460 
461 
462 std::string
464  std::string state, const std::vector<NBNode::Crossing>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
465  const SUMOTime pedClearingTime = TIME2STEPS(5); // compute based on length of the crossing
466  const SUMOTime minPedTime = TIME2STEPS(4); // compute: must be able to reach the middle of the second "Richtungsfahrbahn"
467  const std::string orig = state;
468  state = patchStateForCrossings(state, crossings, fromEdges, toEdges);
469  if (orig == state) {
470  // add step
471  logic->addStep(greenTime, state);
472  } else {
473  const SUMOTime pedTime = greenTime - pedClearingTime;
474  if (pedTime >= minPedTime) {
475  // ensure clearing time for pedestrians
476  const size_t pedStates = crossings.size();
477  logic->addStep(pedTime, state);
478  state = state.substr(0, state.size() - pedStates) + std::string(pedStates, 'r');
479  logic->addStep(pedClearingTime, state);
480  } else {
481  state = orig;
482  // not safe for pedestrians.
483  logic->addStep(greenTime, state);
484  }
485  }
486  return state;
487 }
488 
489 
490 std::string
491 NBOwnTLDef::patchStateForCrossings(const std::string& state, const std::vector<NBNode::Crossing>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
492  std::string result = state;
493  const unsigned int pos = (unsigned int)(state.size() - crossings.size()); // number of controlled vehicle links
494  for (int ic = 0; ic < (int)crossings.size(); ++ic) {
495  const int i1 = pos + ic;
496  const NBNode::Crossing& cross = crossings[ic];
497  bool isForbidden = false;
498  for (unsigned int i2 = 0; i2 < pos && !isForbidden; ++i2) {
499  // only check connections at this crossings node
500  if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.node) {
501  for (EdgeVector::const_iterator it = cross.edges.begin(); it != cross.edges.end(); ++it) {
502  const NBEdge* edge = *it;
503  const LinkDirection i2dir = cross.node->getDirection(fromEdges[i2], toEdges[i2]);
504  if (state[i2] != 'r' && (edge == fromEdges[i2] ||
505  (edge == toEdges[i2] && (i2dir == LINKDIR_STRAIGHT || i2dir == LINKDIR_PARTLEFT || i2dir == LINKDIR_PARTRIGHT)))) {
506  isForbidden = true;
507  break;
508  }
509  }
510  }
511  }
512  if (!isForbidden) {
513  result[i1] = 'G';
514  } else {
515  result[i1] = 'r';
516  }
517  }
518 
519  // correct behaviour for roads that are in conflict with a pedestrian crossing
520  for (unsigned int i1 = 0; i1 < pos; ++i1) {
521  if (result[i1] == 'G') {
522  for (int ic = 0; ic < (int)crossings.size(); ++ic) {
523  const NBNode::Crossing& crossing = crossings[ic];
524  if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.node) {
525  const int i2 = pos + ic;
526  if (result[i2] == 'G' && crossing.node->mustBrakeForCrossing(fromEdges[i1], toEdges[i1], crossing)) {
527  result[i1] = 'g';
528  break;
529  }
530  }
531  }
532  }
533  }
534  return result;
535 }
536 
537 
538 void
540 
541 
542 void
544  collectAllLinks();
545 }
546 
547 
548 void
550  // assign participating nodes to the request
551  collectNodes();
552  // collect the information about participating edges and links
553  collectEdges();
554  collectLinks();
555 }
556 
557 
558 void
560  // set the information about the link's positions within the tl into the
561  // edges the links are starting at, respectively
562  for (NBConnectionVector::const_iterator j = myControlledLinks.begin(); j != myControlledLinks.end(); ++j) {
563  const NBConnection& conn = *j;
564  NBEdge* edge = conn.getFrom();
565  edge->setControllingTLInformation(conn, getID());
566  }
567 }
568 
569 
570 void
571 NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
572  const EdgeVector& /*outgoing*/) {}
573 
574 
575 void
576 NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
577  NBEdge* /*by*/, int /*byLane*/) {}
578 
579 
580 void
583  assert(myControlledNodes.size() > 0);
584  // there are basically 2 cases for controlling multiple nodes
585  // a) a complex (unjoined) intersection. Here, internal junctions should
586  // not be needed since real nodes are used instead
587  // b) two far-away junctions which shall be coordinated
588  // This is likely to mess up the bestPair computation for each
589  // individual node and thus generate incorrect needsCont data
590  //
591  // Therefore we compute needsCont for individual nodes which doesn't
592  // matter for a) and is better for b)
593  myNeedsContRelation.clear();
594  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
595  NBNode* n = *i;
596  NBOwnTLDef dummy(DUMMY_ID, n, 0, TLTYPE_STATIC);
598  dummy.computeLogicAndConts(0, true);
599  myNeedsContRelation.insert(dummy.myNeedsContRelation.begin(), dummy.myNeedsContRelation.end());
600  n->removeTrafficLight(&dummy);
601  }
603  }
604 
605 }
606 
607 
610  EdgeVector result = incoming;
611  // do not sele
612  for (EdgeVector::iterator it = result.begin(); it != result.end();) {
613  if ((*it)->getConnections().size() == 0 || (*it)->isInnerEdge()) {
614  it = result.erase(it);
615  } else {
616  ++it;
617  }
618  }
619  return result;
620 }
621 
622 
623 std::string
624 NBOwnTLDef::allowFollowersOfChosen(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
625  bool check = true;
626  while (check) {
627  check = false;
628  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
629  if (state[i1] == 'G') {
630  continue;
631  }
632  bool followsChosen = false;
633  for (int i2 = 0; i2 < (int)fromEdges.size() && !followsChosen; ++i2) {
634  if (state[i2] == 'G' && fromEdges[i1] == toEdges[i2]) {
635  followsChosen = true;
636  }
637  }
638  if (followsChosen) {
639  state[i1] = 'G';
640  check = true;
641  }
642  }
643  }
644  return state;
645 }
646 
647 
648 std::string
649 NBOwnTLDef::correctConflicting(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
650  const std::vector<bool>& isTurnaround,
651  const std::vector<int>& fromLanes,
652  const std::vector<bool>& hadGreenMajor,
653  bool& haveForbiddenLeftMover,
654  std::vector<bool>& rightTurnConflicts) {
655  const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
656  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
657  if (state[i1] != 'G') {
658  continue;
659  }
660  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
661  if ((state[i2] == 'G' || state[i2] == 'g')) {
663  fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
664  rightTurnConflicts[i1] = true;
665  }
666  if (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true, controlledWithin) || rightTurnConflicts[i1]) {
667  state[i1] = 'g';
668  myNeedsContRelation.insert(StreamPair(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2]));
669  if (!isTurnaround[i1] && !hadGreenMajor[i1]) {
670  haveForbiddenLeftMover = true;
671  }
672  }
673  }
674  }
675  }
676  return state;
677 }
678 
679 /****************************************************************************/
#define MIN_GREEN_TIME
Definition: NBOwnTLDef.cpp:52
static std::string patchStateForCrossings(const std::string &state, const std::vector< NBNode::Crossing > &crossings, const EdgeVector &fromEdges, const EdgeVector &toEdges)
compute phase state in regard to pedestrian crossings
Definition: NBOwnTLDef.cpp:491
The link is a partial left direction.
The link has green light, may pass.
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 myType
The algorithm type for the traffic light.
#define DUMMY_ID
Definition: NBOwnTLDef.cpp:51
long long int SUMOTime
Definition: SUMOTime.h:43
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
void closeBuilding()
closes the building process
RightOnRedConflicts myRightOnRedConflicts
A SUMO-compliant built logic for a traffic light.
TrafficLightType getType() const
get the algorithm type (static etc..)
The link has green light, has to brake.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProgramID() const
Returns the ProgramID.
std::string correctConflicting(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< bool > &isTurnaround, const std::vector< int > &fromLanes, const std::vector< bool > &hadGreenMajor, bool &haveForbiddenLeftMover, std::vector< bool > &rightTurnConflicts)
change &#39;G&#39; to &#39;g&#39; for conflicting connections
Definition: NBOwnTLDef.cpp:649
The representation of a single edge during network building.
Definition: NBEdge.h:70
std::string allowFollowersOfChosen(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges)
allow connections that follow on of the chosen edges
Definition: NBOwnTLDef.cpp:624
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
Definition: NBEdge.cpp:1889
void collectNodes()
Collects the nodes participating in this traffic light.
Definition: NBOwnTLDef.cpp:539
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:61
The base class for traffic light logic definitions.
static bool hasCrossing(const NBEdge *from, const NBEdge *to, const std::vector< NBNode::Crossing > &crossings)
compute whether the given connection is crossed by pedestrians
Definition: NBOwnTLDef.cpp:444
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
NBTrafficLightLogic * computeLogicAndConts(unsigned int brakingTimeSeconds, bool onlyConts=false)
helper function for myCompute
Definition: NBOwnTLDef.cpp:192
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
static EdgeVector getConnectedOuterEdges(const EdgeVector &incoming)
get edges that have connections
Definition: NBOwnTLDef.cpp:609
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:322
std::vector< Connection > getConnectionsFromLane(unsigned int lane) const
Returns connections from a given lane.
Definition: NBEdge.cpp:779
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:200
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
Definition: NBOwnTLDef.cpp:159
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
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:1263
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:65
virtual void collectEdges()
Build the list of participating edges.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
bool mustBrakeForCrossing(const NBEdge *const from, const NBEdge *const to, const Crossing &crossing) const
Returns the information whether the described flow must brake for the given crossing.
Definition: NBNode.cpp:1257
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
Definition: NBOwnTLDef.cpp:576
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:132
bool myHaveSinglePhase
Whether left-mover should not have an additional phase.
Definition: NBOwnTLDef.h:268
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:345
void setPhaseDuration(unsigned int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
~NBOwnTLDef()
Destructor.
Definition: NBOwnTLDef.cpp:79
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1834
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
The link is a (hard) right direction.
static const std::string DefaultProgramID
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
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream&#39;s direction.
Definition: NBNode.cpp:1427
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:1261
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:105
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.
NBOwnTLDef(const std::string &id, const std::vector< NBNode * > &junctions, SUMOTime offset, TrafficLightType type)
Constructor.
Definition: NBOwnTLDef.cpp:57
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:369
void setTLControllingInformation(const NBEdgeCont &ec) const
Informs edges about being controlled by a tls.
Definition: NBOwnTLDef.cpp:559
void collectLinks()
Collects the links participating in this traffic light If a link could not be found.
Definition: NBOwnTLDef.cpp:543
SUMOReal getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
Definition: NBOwnTLDef.cpp:89
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
NBTrafficLightLogic * myCompute(const NBEdgeCont &ec, unsigned int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
Definition: NBOwnTLDef.cpp:187
static SUMOReal getMinAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:172
const NBNode * node
The parent node of this crossing.
Definition: NBNode.h:137
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:139
Represents a single node (junction) during network building.
Definition: NBNode.h:74
A definition of a pedestrian crossing.
Definition: NBNode.h:132
#define SUMOReal
Definition: config.h:214
void initNeedsContRelation() const
Definition: NBOwnTLDef.cpp:581
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:56
#define NUMERICAL_EPS
Definition: config.h:161
data structure for caching needsCont information
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:54
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
Sorts edges by their priority within the node they end at.
Definition: NBOwnTLDef.h:251
void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
Definition: NBOwnTLDef.cpp:549
NBConnectionVector myControlledLinks
The list of controlled links.
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2126
int getToPrio(const NBEdge *const e)
Returns this edge&#39;s priority at the node it ends at.
Definition: NBOwnTLDef.cpp:83
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:571
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:361