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