Eclipse SUMO - Simulation of Urban MObility
NBOwnTLDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // A traffic light logics which must be computed (only nodes/edges are given)
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <vector>
28 #include <cassert>
29 #include <iterator>
31 #include "NBNode.h"
32 #include "NBOwnTLDef.h"
33 #include "NBTrafficLightLogic.h"
36 #include <utils/common/ToString.h>
38 #include <utils/options/Option.h>
39 
40 #define HEIGH_WEIGHT 2
41 #define LOW_WEIGHT .5;
42 
43 #define MIN_GREEN_TIME 5
44 
45 //#define DEBUG_STREAM_ORDERING
46 //#define DEBUG_PHASES
47 //#define DEBUGCOND (getID() == "cluster_251050941_280598736_280598739_28902891_3142549227_3142550438")
48 //#define DEBUGEDGE(edge) (edge->getID() == "23209153#1" || edge->getID() == "319583927#0")
49 //#define DEBUGCOND (true)
50 //#define DEBUGEDGE(edge) (true)
51 
52 // ===========================================================================
53 // member method definitions
54 // ===========================================================================
55 NBOwnTLDef::NBOwnTLDef(const std::string& id,
56  const std::vector<NBNode*>& junctions, SUMOTime offset,
57  TrafficLightType type) :
58  NBTrafficLightDefinition(id, junctions, DefaultProgramID, offset, type),
59  myHaveSinglePhase(false) {
60 }
61 
62 
63 NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
64  TrafficLightType type) :
65  NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type),
66  myHaveSinglePhase(false) {
67 }
68 
69 
70 NBOwnTLDef::NBOwnTLDef(const std::string& id, SUMOTime offset,
71  TrafficLightType type) :
72  NBTrafficLightDefinition(id, DefaultProgramID, offset, type),
73  myHaveSinglePhase(false) {
74 }
75 
76 
78 
79 
80 int
81 NBOwnTLDef::getToPrio(const NBEdge* const e) {
82  return e->getJunctionPriority(e->getToNode());
83 }
84 
85 
86 double
88  switch (dir) {
89  case LINKDIR_STRAIGHT:
90  case LINKDIR_PARTLEFT:
91  case LINKDIR_PARTRIGHT:
92  return HEIGH_WEIGHT;
93  case LINKDIR_LEFT:
94  case LINKDIR_RIGHT:
95  return LOW_WEIGHT;
96  default:
97  break;
98  }
99  return 0;
100 }
101 
102 double
104  double val = 0;
105  for (int e1l = 0; e1l < e1->getNumLanes(); e1l++) {
106  std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
107  for (int e2l = 0; e2l < e2->getNumLanes(); e2l++) {
108  std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
109  for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
110  if (e1->getTurnDestination() == (*e1c).toEdge) {
111  continue;
112  }
113  for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
114  if (e2->getTurnDestination() == (*e2c).toEdge) {
115  continue;
116  }
117  const double sign = (forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge, true)
118  || forbids(e2, (*e2c).toEdge, e1, (*e1c).toEdge, true)) ? -1 : 1;
119  double w1;
120  double w2;
121  if (e1->getJunctionPriority(e1->getToNode()) == e2->getJunctionPriority(e2->getToNode())) {
122  w1 = getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
123  w2 = getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
124  } else {
125  if (e1->getJunctionPriority(e1->getToNode()) > e2->getJunctionPriority(e2->getToNode())) {
126  w1 = HEIGH_WEIGHT;
127  w2 = LOW_WEIGHT;
128  } else {
129  w1 = LOW_WEIGHT;
130  w2 = HEIGH_WEIGHT;
131  }
132  if (sign == -1) {
133  // extra penalty if edges with different junction priority are in conflict
134  w1 *= 2;
135  w2 *= 2;
136  }
137  }
138  val += sign * w1;
139  val += sign * w2;
140 #ifdef DEBUG_STREAM_ORDERING
141  if (DEBUGCOND && DEBUGEDGE(e2) && DEBUGEDGE(e1)) {
142  std::cout << " sign=" << sign << " w1=" << w1 << " w2=" << w2 << " val=" << val
143  << " c1=" << (*e1c).getDescription(e1)
144  << " c2=" << (*e2c).getDescription(e2)
145  << "\n";
146  }
147 #endif
148  }
149  }
150  }
151  }
152 #ifdef DEBUG_STREAM_ORDERING
153  if (DEBUGCOND && DEBUGEDGE(e2) && DEBUGEDGE(e1)) {
154  std::cout << " computeUnblockedWeightedStreamNumber e1=" << e1->getID() << " e2=" << e2->getID() << " val=" << val << "\n";
155  }
156 #endif
157  return val;
158 }
159 
160 
161 std::pair<NBEdge*, NBEdge*>
163  std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(nullptr), static_cast<NBEdge*>(nullptr));
164  double bestValue = -std::numeric_limits<double>::max();
165  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
166  for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
167  const double value = computeUnblockedWeightedStreamNumber(*i, *j);
168  if (value > bestValue) {
169  bestValue = value;
170  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
171  } else if (value == bestValue) {
172  const double ca = GeomHelper::getMinAngleDiff((*i)->getAngleAtNode((*i)->getToNode()), (*j)->getAngleAtNode((*j)->getToNode()));
173  const double oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
174  if (fabs(oa - ca) < NUMERICAL_EPS) { // break ties by id
175  if (bestPair.first->getID() < (*i)->getID()) {
176  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
177  }
178  } else if (oa < ca) {
179  bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
180  }
181  }
182  }
183  }
184  if (bestValue <= 0) {
185  // do not group edges
186  bestPair.second = nullptr;
187 
188  }
189 #ifdef DEBUG_STREAM_ORDERING
190  if (DEBUGCOND) {
191  std::cout << " getBestCombination bestValue=" << bestValue << " best=" << Named::getIDSecure(bestPair.first) << ", " << Named::getIDSecure(bestPair.second) << "\n";
192  }
193 #endif
194  return bestPair;
195 }
196 
197 
198 std::pair<NBEdge*, NBEdge*>
200  if (incoming.size() == 1) {
201  // only one there - return the one
202  std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(nullptr));
203  incoming.clear();
204  return ret;
205  }
206  // determine the best combination
207  // by priority, first
208  EdgeVector used;
209  std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
210  used.push_back(*incoming.begin()); // the first will definitely be used
211  // get the ones with the same priority
212  int prio = getToPrio(*used.begin());
213  for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio == getToPrio(*i); ++i) {
214  used.push_back(*i);
215  }
216  // if there only lower priorised, use these, too
217  if (used.size() < 2) {
218  used = incoming;
219  }
220  std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
221 #ifdef DEBUG_STREAM_ORDERING
222  if (DEBUGCOND) {
223  std::cout << "getBestPair tls=" << getID() << " incoming=" << toString(incoming) << " prio=" << prio << " used=" << toString(used) << " best=" << Named::getIDSecure(ret.first) << ", " << Named::getIDSecure(ret.second) << "\n";
224  }
225 #endif
226 
227  incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
228  if (ret.second != nullptr) {
229  incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
230  }
231  return ret;
232 }
233 
235 NBOwnTLDef::myCompute(int brakingTimeSeconds) {
236  return computeLogicAndConts(brakingTimeSeconds);
237 }
238 
240 NBOwnTLDef::computeLogicAndConts(int brakingTimeSeconds, bool onlyConts) {
241  myNeedsContRelation.clear();
242  myRightOnRedConflicts.clear();
243  const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
244  const SUMOTime leftTurnTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.left-green.time"));
245  const SUMOTime minMinDur = myType == TLTYPE_STATIC ? UNSPECIFIED_DURATION : TIME2STEPS(OptionsCont::getOptions().getInt("tls.min-dur"));
246  const SUMOTime maxDur = myType == TLTYPE_STATIC ? UNSPECIFIED_DURATION : TIME2STEPS(OptionsCont::getOptions().getInt("tls.max-dur"));
247 
248  // build complete lists first
249  const EdgeVector& incoming = getIncomingEdges();
250  EdgeVector fromEdges, toEdges;
251  std::vector<bool> isTurnaround;
252  std::vector<bool> hasTurnLane;
253  std::vector<int> fromLanes;
254  std::vector<int> toLanes;
255  int noLinksAll = 0;
256  for (NBEdge* const fromEdge : incoming) {
257  const int numLanes = fromEdge->getNumLanes();
258  for (int i2 = 0; i2 < numLanes; i2++) {
259  bool hasLeft = false;
260  bool hasStraight = false;
261  bool hasRight = false;
262  bool hasTurnaround = false;
263  for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
264  if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
265  continue;
266  }
267  fromEdges.push_back(fromEdge);
268  fromLanes.push_back(i2);
269  toLanes.push_back(approached.toLane);
270  toEdges.push_back(approached.toEdge);
271  if (approached.toEdge != nullptr) {
272  isTurnaround.push_back(fromEdge->isTurningDirectionAt(approached.toEdge));
273  } else {
274  isTurnaround.push_back(true);
275  }
276  LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, approached.toEdge);
277  if (dir == LINKDIR_STRAIGHT) {
278  hasStraight = true;
279  } else if (dir == LINKDIR_RIGHT || dir == LINKDIR_PARTRIGHT) {
280  hasRight = true;
281  } else if (dir == LINKDIR_LEFT || dir == LINKDIR_PARTLEFT) {
282  hasLeft = true;
283  } else if (dir == LINKDIR_TURN) {
284  hasTurnaround = true;
285  }
286  noLinksAll++;
287  }
288  for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
289  if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
290  continue;
291  }
292  hasTurnLane.push_back(
293  (hasLeft && !hasStraight && !hasRight)
294  || (!hasLeft && !hasTurnaround && hasRight));
295  }
296  //std::cout << " from=" << fromEdge->getID() << "_" << i2 << " hasTurnLane=" << hasTurnLane.back() << " s=" << hasStraight << " l=" << hasLeft << " r=" << hasRight << " t=" << hasTurnaround << "\n";
297  }
298  }
299  // collect crossings
300  std::vector<NBNode::Crossing*> crossings;
301  for (NBNode* const node : myControlledNodes) {
302  const std::vector<NBNode::Crossing*>& c = node->getCrossings();
303  if (!onlyConts) {
304  // set tl indices for crossings
305  node->setCrossingTLIndices(getID(), noLinksAll);
306  }
307  copy(c.begin(), c.end(), std::back_inserter(crossings));
308  noLinksAll += (int)c.size();
309  }
310 
311  NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noLinksAll, myOffset, myType);
312  EdgeVector toProc = getConnectedOuterEdges(incoming);
313  const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
314  const SUMOTime allRedTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.allred.time"));
315  const double minorLeftSpeedThreshold = OptionsCont::getOptions().getFloat("tls.minor-left.max-speed");
316  // left-turn phases do not work well for joined tls, so we build incoming instead
317  const double groupOpposites = (OptionsCont::getOptions().getString("tls.layout") == "opposites"
318  && (myControlledNodes.size() <= 2 || corridorLike()));
319 
320  // build all phases
321  std::vector<int> greenPhases; // indices of green phases
322  std::vector<bool> hadGreenMajor(noLinksAll, false);
323  while (toProc.size() > 0) {
324  bool groupTram = false;
325  bool groupOther = false;
326  std::pair<NBEdge*, NBEdge*> chosen;
327  if (groupOpposites) {
328  if (incoming.size() == 2) {
329  // if there are only 2 incoming edges we need to decide whether they are a crossing or a "continuation"
330  // @node: this heuristic could be extended to also check the number of outgoing edges
331  double angle = fabs(NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
332  // angle would be 180 for straight opposing incoming edges
333  if (angle < 135) {
334  chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(nullptr));
335  toProc.erase(toProc.begin());
336  } else {
337  chosen = getBestPair(toProc);
338  }
339  } else {
340  chosen = getBestPair(toProc);
341  if (chosen.second == nullptr && chosen.first->getPermissions() == SVC_TRAM) {
342  groupTram = true;
343  for (auto it = toProc.begin(); it != toProc.end();) {
344  if ((*it)->getPermissions() == SVC_TRAM) {
345  it = toProc.erase(it);
346  } else {
347  it++;
348  }
349  }
350  }
351  }
352  } else {
353  NBEdge* chosenEdge = toProc[0];
354  chosen = std::pair<NBEdge*, NBEdge*>(chosenEdge, static_cast<NBEdge*>(nullptr));
355  toProc.erase(toProc.begin());
356  SVCPermissions perms = chosenEdge->getPermissions();
357  if (perms == SVC_TRAM) {
358  groupTram = true;
359  } else if ((perms & ~(SVC_PEDESTRIAN | SVC_BICYCLE | SVC_DELIVERY)) == 0) {
360  groupOther = true;
361  }
362  // group all edges with the same permissions into a single phase (later)
363  if (groupTram || groupOther) {
364  for (auto it = toProc.begin(); it != toProc.end();) {
365  if ((*it)->getPermissions() == perms) {
366  it = toProc.erase(it);
367  } else {
368  it++;
369  }
370  }
371  }
372  }
373  int pos = 0;
374  std::string state((int) noLinksAll, 'r');
375 #ifdef DEBUG_PHASES
376  if (DEBUGCOND) {
377  std::cout << " computing " << getID() << " prog=" << getProgramID() << " cho1=" << Named::getIDSecure(chosen.first) << " cho2=" << Named::getIDSecure(chosen.second) << " toProc=" << toString(toProc) << " bentPrio=" << chosen.first->getToNode()->isBentPriority() << "\n";
378  }
379 #endif
380  // plain straight movers
381  double maxSpeed = 0;
382  bool haveGreen = false;
383  for (const NBEdge* const fromEdge : incoming) {
384  const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
385  const int numLanes = fromEdge->getNumLanes();
386  for (int i2 = 0; i2 < numLanes; i2++) {
387  for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
388  if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
389  continue;
390  }
391  if (inChosen) {
392  state[pos] = 'G';
393  haveGreen = true;
394  maxSpeed = MAX2(maxSpeed, fromEdge->getSpeed());
395  } else {
396  state[pos] = 'r';
397  }
398  ++pos;
399  }
400  }
401  }
402  if (!haveGreen) {
403  continue;
404  }
405 
406 #ifdef DEBUG_PHASES
407  if (DEBUGCOND) {
408  std::cout << " state after plain straight movers " << state << "\n";
409  }
410 #endif
411  // correct behaviour for those that are not in chosen, but may drive, though
412  state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
413  if (groupTram) {
414  state = allowByVClass(state, fromEdges, toEdges, SVC_TRAM);
415  } else if (groupOther) {
416  state = allowByVClass(state, fromEdges, toEdges, SVC_PEDESTRIAN | SVC_BICYCLE | SVC_DELIVERY);
417  }
418 #ifdef DEBUG_PHASES
419  if (DEBUGCOND) {
420  std::cout << " state after grouping by vClass " << state << "\n";
421  }
422 #endif
423  if (groupOpposites || chosen.first->getToNode()->getType() == NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED) {
424  state = allowUnrelated(state, fromEdges, toEdges, isTurnaround, crossings);
425  }
426 #ifdef DEBUG_PHASES
427  if (DEBUGCOND) {
428  std::cout << " state after finding allowUnrelated " << state << "\n";
429  }
430 #endif
431  // correct behaviour for those that have to wait (mainly left-mover)
432  bool haveForbiddenLeftMover = false;
433  std::vector<bool> rightTurnConflicts(pos, false);
434  state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
435  for (int i1 = 0; i1 < pos; ++i1) {
436  if (state[i1] == 'G') {
437  hadGreenMajor[i1] = true;
438  }
439  }
440 #ifdef DEBUG_PHASES
441  if (DEBUGCOND) {
442  std::cout << " state after correcting left movers=" << state << "\n";
443  }
444 #endif
445 
446  std::vector<bool> leftGreen(pos, false);
447  // check whether at least one left-turn lane exist
448  bool foundLeftTurnLane = false;
449  for (int i1 = 0; i1 < pos; ++i1) {
450  if (state[i1] == 'g' && !rightTurnConflicts[i1] && hasTurnLane[i1]) {
451  foundLeftTurnLane = true;
452  }
453  }
454  const bool buildLeftGreenPhase = (haveForbiddenLeftMover && !myHaveSinglePhase && leftTurnTime > 0 && foundLeftTurnLane
455  && groupOpposites && !groupTram && !groupOther);
456 
457  // find indices for exclusive left green phase and apply option minor-left.max-speed
458  for (int i1 = 0; i1 < pos; ++i1) {
459  if (state[i1] == 'g' && !rightTurnConflicts[i1]
460  // only activate turn-around together with a real left-turn
461  && (!isTurnaround[i1] || (i1 > 0 && leftGreen[i1 - 1]))) {
462  leftGreen[i1] = true;
463  if (fromEdges[i1]->getSpeed() > minorLeftSpeedThreshold) {
464  if (buildLeftGreenPhase) {
465  state[i1] = 'r';
466  //std::cout << " disabling minorLeft " << i1 << " (speed=" << fromEdges[i1]->getSpeed() << " thresh=" << minorLeftSpeedThreshold << ")\n";
467  } else if (!isTurnaround[i1]) {
468  WRITE_WARNING("Minor green from edge '" + fromEdges[i1]->getID() + "' to edge '" + toEdges[i1]->getID() + "' exceeds "
469  + toString(minorLeftSpeedThreshold) + "m/s. Maybe a left-turn lane is missing.");
470  }
471  }
472  }
473  }
474 
475 #ifdef DEBUG_PHASES
476  if (DEBUGCOND) {
477  std::cout << getID() << " state=" << state << " buildLeft=" << buildLeftGreenPhase << " hFLM=" << haveForbiddenLeftMover << " turnLane=" << foundLeftTurnLane
478  << " \nrtC=" << toString(rightTurnConflicts)
479  << " \nhTL=" << toString(hasTurnLane)
480  << " \nlGr=" << toString(leftGreen)
481  << "\n";
482  }
483 #endif
484 
485  const std::string vehicleState = state; // backup state before pedestrian modifications
486  greenPhases.push_back((int)logic->getPhases().size());
487 
488  // 5s at 50km/h, 10s at 80km/h, rounded to full seconds
489  const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
490  SUMOTime minDur = MAX2(minMinDur, TIME2STEPS(floor(minDurBySpeed + 0.5)));
491  if (chosen.first->getPermissions() == SVC_TRAM && (chosen.second == nullptr || chosen.second->getPermissions() == SVC_TRAM)) {
492  // shorter minDuration for tram phase (only if the phase is
493  // exclusively for tram)
494  bool tramExclusive = true;
495  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
496  if (state[i1] == 'G') {
497  SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
498  if (linkPerm != SVC_TRAM) {
499  tramExclusive = false;
500  break;
501  }
502  }
503  }
504  if (tramExclusive) {
505  // one tram per actuated phase
506  minDur = TIME2STEPS(1);
507  }
508  }
509 
510  state = addPedestrianPhases(logic, greenTime, minDur, maxDur, state, crossings, fromEdges, toEdges);
511  // pedestrians have 'r' from here on
512  for (int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
513  state[i1] = 'r';
514  }
515  if (brakingTime > 0) {
516  // build yellow (straight)
517  for (int i1 = 0; i1 < pos; ++i1) {
518  if (state[i1] != 'G' && state[i1] != 'g') {
519  continue;
520  }
521  if ((vehicleState[i1] >= 'a' && vehicleState[i1] <= 'z')
522  && buildLeftGreenPhase
523  && !rightTurnConflicts[i1]
524  && leftGreen[i1]) {
525  continue;
526  }
527  state[i1] = 'y';
528  }
529  // add step
530  logic->addStep(brakingTime, state);
531  // add optional all-red state
532  buildAllRedState(allRedTime, logic, state);
533  }
534 
535 
536  if (buildLeftGreenPhase) {
537  // build left green
538  for (int i1 = 0; i1 < pos; ++i1) {
539  if (state[i1] == 'Y' || state[i1] == 'y') {
540  state[i1] = 'r';
541  continue;
542  }
543  if (leftGreen[i1]) {
544  state[i1] = 'G';
545  }
546  }
547  state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
548  state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
549 
550  // add step
551  logic->addStep(leftTurnTime, state, minDur, maxDur);
552 
553  // build left yellow
554  if (brakingTime > 0) {
555  for (int i1 = 0; i1 < pos; ++i1) {
556  if (state[i1] != 'G' && state[i1] != 'g') {
557  continue;
558  }
559  state[i1] = 'y';
560  }
561  // add step
562  logic->addStep(brakingTime, state);
563  // add optional all-red state
564  buildAllRedState(allRedTime, logic, state);
565  }
566  }
567  }
568  // fix pedestrian crossings that did not get the green light yet
569  if (crossings.size() > 0) {
570  addPedestrianScramble(logic, noLinksAll, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
571  }
572  // add optional red phase if there where no foes
573  if (logic->getPhases().size() == 2 && brakingTime > 0
574  && OptionsCont::getOptions().getInt("tls.red.time") > 0) {
575  const SUMOTime redTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.red.time"));
576  logic->addStep(redTime, std::string(noLinksAll, 'r'));
577  }
578  // fix states to account for custom crossing link indices
579  if (crossings.size() > 0 && !onlyConts) {
581  }
582 
583  SUMOTime totalDuration = logic->getDuration();
584  if (OptionsCont::getOptions().isDefault("tls.green.time") || !OptionsCont::getOptions().isDefault("tls.cycle.time")) {
585  const SUMOTime cycleTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.cycle.time"));
586  // adapt to cycle time by changing the duration of the green phases
587  SUMOTime greenPhaseTime = 0;
588  SUMOTime minGreenDuration = SUMOTime_MAX;
589  for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
590  const SUMOTime dur = logic->getPhases()[*it].duration;
591  greenPhaseTime += dur;
592  minGreenDuration = MIN2(minGreenDuration, dur);
593  }
594  const int patchSeconds = (int)(STEPS2TIME(cycleTime - totalDuration) / greenPhases.size());
595  const int patchSecondsRest = (int)(STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (int)greenPhases.size();
596  //std::cout << "cT=" << cycleTime << " td=" << totalDuration << " pS=" << patchSeconds << " pSR=" << patchSecondsRest << "\n";
597  if (STEPS2TIME(minGreenDuration) + patchSeconds < MIN_GREEN_TIME
598  || STEPS2TIME(minGreenDuration) + patchSeconds + patchSecondsRest < MIN_GREEN_TIME
599  || greenPhases.size() == 0) {
600  if (getID() != DummyID) {
601  WRITE_WARNING("The traffic light '" + getID() + "' cannot be adapted to a cycle time of " + time2string(cycleTime) + ".");
602  }
603  // @todo use a multiple of cycleTime ?
604  } else {
605  for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
606  logic->setPhaseDuration(*it, logic->getPhases()[*it].duration + TIME2STEPS(patchSeconds));
607  }
608  if (greenPhases.size() > 0) {
609  logic->setPhaseDuration(greenPhases.front(), logic->getPhases()[greenPhases.front()].duration + TIME2STEPS(patchSecondsRest));
610  }
611  totalDuration = logic->getDuration();
612  }
613  }
614 
616  // this computation only makes sense for single nodes
617  myNeedsContRelationReady = (myControlledNodes.size() == 1);
618  if (totalDuration > 0) {
619  if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
620  WRITE_WARNING("The traffic light '" + getID() + "' has a high cycle time of " + time2string(totalDuration) + ".");
621  }
622  logic->closeBuilding();
623  return logic;
624  } else {
625  delete logic;
626  return nullptr;
627  }
628 }
629 
630 
631 bool
632 NBOwnTLDef::hasCrossing(const NBEdge* from, const NBEdge* to, const std::vector<NBNode::Crossing*>& crossings) {
633  assert(to != 0);
634  for (auto c : crossings) {
635  const NBNode::Crossing& cross = *c;
636  // only check connections at this crossings node
637  if (to->getFromNode() == cross.node) {
638  for (EdgeVector::const_iterator it_e = cross.edges.begin(); it_e != cross.edges.end(); ++it_e) {
639  const NBEdge* edge = *it_e;
640  if (edge == from || edge == to) {
641  return true;
642  }
643  }
644  }
645  }
646  return false;
647 }
648 
649 
650 std::string
652  SUMOTime minDur, SUMOTime maxDur,
653  std::string state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
654  // compute based on length of the crossing if not set by the user
655  const SUMOTime pedClearingTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-clearance.time"));
656  // compute if not set by user: must be able to reach the middle of the second "Richtungsfahrbahn"
657  const SUMOTime minPedTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-min.time"));
658  const std::string orig = state;
659  state = patchStateForCrossings(state, crossings, fromEdges, toEdges);
660  if (orig == state) {
661  // add step
662  logic->addStep(greenTime, state, minDur, maxDur);
663  } else {
664  const SUMOTime pedTime = greenTime - pedClearingTime;
665  if (pedTime >= minPedTime) {
666  // ensure clearing time for pedestrians
667  const int pedStates = (int)crossings.size();
668  logic->addStep(pedTime, state, minDur, maxDur);
669  state = state.substr(0, state.size() - pedStates) + std::string(pedStates, 'r');
670  logic->addStep(pedClearingTime, state);
671  } else {
672  state = orig;
673  // not safe for pedestrians.
674  logic->addStep(greenTime, state, minDur, maxDur);
675  }
676  }
677  return state;
678 }
679 
680 
681 std::string
682 NBOwnTLDef::patchStateForCrossings(const std::string& state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
683  std::string result = state;
684  const int pos = (int)(state.size() - crossings.size()); // number of controlled vehicle links
685  for (int ic = 0; ic < (int)crossings.size(); ++ic) {
686  const int i1 = pos + ic;
687  const NBNode::Crossing& cross = *crossings[ic];
688  bool isForbidden = false;
689  for (int i2 = 0; i2 < pos && !isForbidden; ++i2) {
690  // only check connections at this crossings node
691  if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.node) {
692  for (EdgeVector::const_iterator it = cross.edges.begin(); it != cross.edges.end(); ++it) {
693  const NBEdge* edge = *it;
694  const LinkDirection i2dir = cross.node->getDirection(fromEdges[i2], toEdges[i2]);
695  if (state[i2] != 'r' && state[i2] != 's' && (edge == fromEdges[i2] ||
696  (edge == toEdges[i2] && (i2dir == LINKDIR_STRAIGHT || i2dir == LINKDIR_PARTLEFT || i2dir == LINKDIR_PARTRIGHT)))) {
697  isForbidden = true;
698  break;
699  }
700  }
701  }
702  }
703  if (!isForbidden) {
704  result[i1] = 'G';
705  } else {
706  result[i1] = 'r';
707  }
708  }
709 
710  // correct behaviour for roads that are in conflict with a pedestrian crossing
711  for (int i1 = 0; i1 < pos; ++i1) {
712  if (result[i1] == 'G') {
713  for (int ic = 0; ic < (int)crossings.size(); ++ic) {
714  const NBNode::Crossing& crossing = *crossings[ic];
715  if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.node) {
716  const int i2 = pos + ic;
717  if (result[i2] == 'G' && crossing.node->mustBrakeForCrossing(fromEdges[i1], toEdges[i1], crossing)) {
718  result[i1] = 'g';
719  break;
720  }
721  }
722  }
723  }
724  }
725  return result;
726 }
727 
728 
729 void
731  collectAllLinks();
732 }
733 
734 
735 void
737  // set the information about the link's positions within the tl into the
738  // edges the links are starting at, respectively
739  for (NBConnectionVector::const_iterator j = myControlledLinks.begin(); j != myControlledLinks.end(); ++j) {
740  const NBConnection& conn = *j;
741  NBEdge* edge = conn.getFrom();
742  edge->setControllingTLInformation(conn, getID());
743  }
744 }
745 
746 
747 void
748 NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
749  const EdgeVector& /*outgoing*/) {}
750 
751 
752 void
753 NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
754  NBEdge* /*by*/, int /*byLane*/) {}
755 
756 
757 void
760  if (myControlledNodes.size() > 0) {
761  // we use a dummy node just to maintain const-correctness
762  myNeedsContRelation.clear();
765  NBTrafficLightLogic* tllDummy = dummy.computeLogicAndConts(0, true);
766  delete tllDummy;
768  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
769  (*i)->removeTrafficLight(&dummy);
770  }
771  }
773  }
774 }
775 
776 
779  EdgeVector result = incoming;
780  for (EdgeVector::iterator it = result.begin(); it != result.end();) {
781  if ((*it)->getConnections().size() == 0 || (*it)->isInsideTLS()) {
782  it = result.erase(it);
783  } else {
784  ++it;
785  }
786  }
787  return result;
788 }
789 
790 
791 std::string
792 NBOwnTLDef::allowCompatible(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
793  const std::vector<int>& fromLanes, const std::vector<int>& toLanes) {
794  state = allowSingleEdge(state, fromEdges);
795  state = allowFollowers(state, fromEdges, toEdges);
796  state = allowPredecessors(state, fromEdges, toEdges, fromLanes, toLanes);
797  return state;
798 }
799 
800 
801 std::string
802 NBOwnTLDef::allowSingleEdge(std::string state, const EdgeVector& fromEdges) {
803  // if only one edge has green, ensure sure that all connections from that edge are green
804  const int size = (int)fromEdges.size();
805  NBEdge* greenEdge = nullptr;
806  for (int i1 = 0; i1 < size; ++i1) {
807  if (state[i1] == 'G') {
808  if (greenEdge == nullptr) {
809  greenEdge = fromEdges[i1];
810  } else if (greenEdge != fromEdges[i1]) {
811  return state;
812  }
813  }
814  }
815  if (greenEdge != nullptr) {
816  for (int i1 = 0; i1 < size; ++i1) {
817  if (fromEdges[i1] == greenEdge) {
818  state[i1] = 'G';
819  }
820  }
821  }
822  return state;
823 }
824 
825 
826 std::string
827 NBOwnTLDef::allowFollowers(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
828  // check continuation within joined traffic lights
829  bool check = true;
830  while (check) {
831  check = false;
832  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
833  if (state[i1] == 'G') {
834  continue;
835  }
836  //if (forbidden(state, i1, fromEdges, toEdges)) {
837  // continue;
838  //}
839  bool followsChosen = false;
840  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
841  if (state[i2] == 'G' && fromEdges[i1] == toEdges[i2]) {
842  followsChosen = true;
843  break;
844  }
845  }
846  if (followsChosen) {
847  state[i1] = 'G';
848  check = true;
849  }
850  }
851  }
852  return state;
853 }
854 
855 
856 std::string
857 NBOwnTLDef::allowPredecessors(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
858  const std::vector<int>& fromLanes, const std::vector<int>& toLanes) {
859  // also allow predecessors of chosen edges if the lanes match and there is no conflict
860  // (must be done after the followers are done because followers are less specific)
861  bool check = true;
862  while (check) {
863  check = false;
864  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
865  if (state[i1] == 'G') {
866  continue;
867  }
868  if (forbidden(state, i1, fromEdges, toEdges)) {
869  continue;
870  }
871  bool preceedsChosen = false;
872  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
873  if (state[i2] == 'G' && fromEdges[i2] == toEdges[i1]
874  && fromLanes[i2] == toLanes[i1]) {
875  preceedsChosen = true;
876  break;
877  }
878  }
879  if (preceedsChosen) {
880  state[i1] = 'G';
881  check = true;
882  }
883  }
884  }
885  return state;
886 }
887 
888 
889 std::string
890 NBOwnTLDef::allowUnrelated(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
891  const std::vector<bool>& isTurnaround,
892  const std::vector<NBNode::Crossing*>& crossings) {
893  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
894  if (state[i1] == 'G') {
895  continue;
896  }
897  bool isForbidden = false;
898  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
899  if (state[i2] == 'G' && !isTurnaround[i2] &&
900  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
901  isForbidden = true;
902  break;
903  }
904  }
905  if (!isForbidden && !hasCrossing(fromEdges[i1], toEdges[i1], crossings)) {
906  state[i1] = 'G';
907  }
908  }
909  return state;
910 }
911 
912 
913 std::string
914 NBOwnTLDef::allowByVClass(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges, SVCPermissions perm) {
915  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
916  SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
917  if ((linkPerm & ~perm) == 0) {
918  state[i1] = 'G';
919  }
920  }
921  return state;
922 }
923 
924 
925 bool
926 NBOwnTLDef::forbidden(const std::string& state, int index, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
927  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
928  if (state[i2] == 'G' && foes(fromEdges[i2], toEdges[i2], fromEdges[index], toEdges[index])) {
929  return true;
930  }
931  }
932  return false;
933 }
934 
935 
936 std::string
937 NBOwnTLDef::correctConflicting(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
938  const std::vector<bool>& isTurnaround,
939  const std::vector<int>& fromLanes,
940  const std::vector<bool>& hadGreenMajor,
941  bool& haveForbiddenLeftMover,
942  std::vector<bool>& rightTurnConflicts) {
943  const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
944  for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
945  if (state[i1] == 'G') {
946  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
947  if ((state[i2] == 'G' || state[i2] == 'g')) {
949  fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
950  rightTurnConflicts[i1] = true;
951  }
952  if (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true, controlledWithin) || rightTurnConflicts[i1]) {
953  state[i1] = 'g';
954  myNeedsContRelation.insert(StreamPair(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2]));
955  if (!isTurnaround[i1] && !hadGreenMajor[i1] && !rightTurnConflicts[i1]) {
956  haveForbiddenLeftMover = true;
957  }
958  }
959  }
960  }
961  }
962  if (state[i1] == 'r') {
963  if (fromEdges[i1]->getToNode()->getType() == NODETYPE_TRAFFIC_LIGHT_RIGHT_ON_RED &&
964  fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) == LINKDIR_RIGHT) {
965  state[i1] = 's';
966  // do not allow right-on-red when in conflict with exclusive left-turn phase
967  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
968  if (state[i2] == 'G' && !isTurnaround[i2] &&
969  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) ||
970  forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
971  const LinkDirection foeDir = fromEdges[i2]->getToNode()->getDirection(fromEdges[i2], toEdges[i2]);
972  if (foeDir == LINKDIR_LEFT || foeDir == LINKDIR_PARTLEFT) {
973  state[i1] = 'r';
974  break;
975  }
976  }
977  }
978  if (state[i1] == 's') {
979  // handle right-on-red conflicts
980  for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
981  if (state[i2] == 'G' && !isTurnaround[i2] &&
982  (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) ||
983  forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
984  myRightOnRedConflicts.insert(std::make_pair(i1, i2));
985  }
986  }
987  }
988  }
989  }
990  }
991  return state;
992 }
993 
994 
995 void
996 NBOwnTLDef::addPedestrianScramble(NBTrafficLightLogic* logic, int noLinksAll, SUMOTime /* greenTime */, SUMOTime brakingTime,
997  const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
998  const int vehLinks = noLinksAll - (int)crossings.size();
999  std::vector<bool> foundGreen(crossings.size(), false);
1000  const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->getPhases();
1001  for (int i = 0; i < (int)phases.size(); ++i) {
1002  const std::string state = phases[i].state;
1003  for (int j = 0; j < (int)crossings.size(); ++j) {
1004  LinkState ls = (LinkState)state[vehLinks + j];
1006  foundGreen[j] = true;
1007  }
1008  }
1009  }
1010  for (int j = 0; j < (int)foundGreen.size(); ++j) {
1011  if (!foundGreen[j]) {
1012 
1013  // add a phase where all pedestrians may walk, (preceded by a yellow phase and followed by a clearing phase)
1014  if (phases.size() > 0) {
1015  bool needYellowPhase = false;
1016  std::string state = phases.back().state;
1017  for (int i1 = 0; i1 < vehLinks; ++i1) {
1018  if (state[i1] == 'G' || state[i1] == 'g') {
1019  state[i1] = 'y';
1020  needYellowPhase = true;
1021  }
1022  }
1023  // add yellow step
1024  if (needYellowPhase && brakingTime > 0) {
1025  logic->addStep(brakingTime, state);
1026  }
1027  }
1028  const SUMOTime pedClearingTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-clearance.time"));
1029  const SUMOTime scrambleTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.scramble.time"));
1030  addPedestrianPhases(logic, scrambleTime + pedClearingTime, UNSPECIFIED_DURATION, UNSPECIFIED_DURATION, std::string(noLinksAll, 'r'), crossings, fromEdges, toEdges);
1031  break;
1032  }
1033  }
1034 }
1035 
1036 
1037 void
1038 NBOwnTLDef::buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic* logic, const std::string& state) {
1039  if (allRedTime > 0) {
1040  // build all-red phase
1041  std::string allRedState = state;
1042  for (int i1 = 0; i1 < (int)state.size(); ++i1) {
1043  if (allRedState[i1] == 'Y' || allRedState[i1] == 'y') {
1044  allRedState[i1] = 'r';
1045  }
1046  }
1047  logic->addStep(allRedTime, allRedState);
1048  }
1049 }
1050 
1051 void
1053  int minCustomIndex = -1;
1054  int maxCustomIndex = -1;
1055  // collect crossings
1056  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
1057  const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
1058  for (auto crossing : c) {
1059  minCustomIndex = MIN2(minCustomIndex, crossing->customTLIndex);
1060  minCustomIndex = MIN2(minCustomIndex, crossing->customTLIndex2);
1061  maxCustomIndex = MAX2(maxCustomIndex, crossing->customTLIndex);
1062  maxCustomIndex = MAX2(maxCustomIndex, crossing->customTLIndex2);
1063  }
1064  }
1065  // custom crossing linkIndex could lead to longer states. ensure that every index has a state
1066  if (maxCustomIndex >= logic->getNumLinks()) {
1067  logic->setStateLength(maxCustomIndex + 1);
1068  }
1069  // XXX shorter state vectors are possible as well
1070  // XXX if the indices are shuffled the guessed crossing states should be shuffled correspondingly
1071  // XXX initialize the backward index to the same state as the forward index
1072 }
1073 
1074 
1075 int
1079  if (logic != nullptr) {
1080  return logic->getNumLinks() - 1;
1081  } else {
1082  return -1;
1083  }
1084 }
1085 
1086 
1087 bool
1089  if (getID() == DummyID) {
1090  // avoid infinite recursion
1091  return true;
1092  }
1093  assert(myControlledNodes.size() >= 2);
1095  dummy.setParticipantsInformation();
1096  NBTrafficLightLogic* tllDummy = dummy.computeLogicAndConts(0, true);
1097  int greenPhases = 0;
1098  for (const auto& phase : tllDummy->getPhases()) {
1099  if (phase.state.find_first_of("gG") != std::string::npos) {
1100  greenPhases++;
1101  }
1102  }
1103  delete tllDummy;
1104  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
1105  (*i)->removeTrafficLight(&dummy);
1106  }
1107  return greenPhases <= 2;
1108 }
1109 
1110 /****************************************************************************/
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:47
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:175
std::string allowCompatible(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< int > &fromLanes, const std::vector< int > &toLanes)
allow connections that are compatible with the chosen edges
Definition: NBOwnTLDef.cpp:792
#define MIN_GREEN_TIME
Definition: NBOwnTLDef.cpp:43
The link is a partial left direction.
The link has green light, may pass.
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
bool forbidden(const std::string &state, int index, const EdgeVector &fromEdges, const EdgeVector &toEdges)
whether the given index is forbidden by a green link in the current state
Definition: NBOwnTLDef.cpp:926
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:2847
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
Definition: NBOwnTLDef.cpp:736
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:184
TrafficLightType myType
The algorithm type for the traffic light.
long long int SUMOTime
Definition: SUMOTime.h:35
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
int getNumLinks()
Returns the number of participating links.
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:632
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:1843
The link has green light, has to brake.
#define LOW_WEIGHT
Definition: NBOwnTLDef.cpp:41
vehicle is a bicycle
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
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:937
The representation of a single edge during network building.
Definition: NBEdge.h:86
TrafficLightType getType() const
get the algorithm type (static etc..)
vehicle is a small delivery vehicle
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
The link is a 180 degree turn.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:65
vehicle is a light rail
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
The base class for traffic light logic definitions.
T MAX2(T a, T b)
Definition: StdDefs.h:80
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3116
static const SUMOTime UNSPECIFIED_DURATION
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
Definition: Named.h:70
NBEdge * getFrom() const
returns the from-edge (start of the connection)
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:77
#define TIME2STEPS(x)
Definition: SUMOTime.h:59
std::string allowByVClass(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, SVCPermissions perm)
Definition: NBOwnTLDef.cpp:914
static EdgeVector getConnectedOuterEdges(const EdgeVector &incoming)
get edges that have connections
Definition: NBOwnTLDef.cpp:778
SUMOTime myOffset
The offset in the program.
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
Definition: NBOwnTLDef.cpp:199
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
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:1701
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
The link is a straight direction.
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:996
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
void addStep(SUMOTime duration, const std::string &state, const std::vector< int > &next=std::vector< int >(), const std::string &name="", int index=-1)
Adds a phase to the logic.
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:465
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
Definition: NBOwnTLDef.cpp:753
std::string allowFollowers(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges)
Definition: NBOwnTLDef.cpp:827
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:103
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:162
bool myHaveSinglePhase
Whether left-mover should not have an additional phase.
Definition: NBOwnTLDef.h:282
void checkCustomCrossingIndices(NBTrafficLightLogic *logic) const
fix states in regard to custom crossing indices
std::string allowUnrelated(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< bool > &isTurnaround, const std::vector< NBNode::Crossing *> &crossings)
Definition: NBOwnTLDef.cpp:890
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
#define STEPS2TIME(x)
Definition: SUMOTime.h:57
~NBOwnTLDef()
Destructor.
Definition: NBOwnTLDef.cpp:77
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
const std::string & getID() const
Definition: NBEdge.h:1364
NBOwnTLDef(const std::string &id, const std::vector< NBNode *> &junctions, SUMOTime offset, TrafficLightType type)
Constructor.
Definition: NBOwnTLDef.cpp:55
T MIN2(T a, T b)
Definition: StdDefs.h:74
The link is a (hard) right direction.
static const std::string DefaultProgramID
const std::string & getProgramID() const
Returns the ProgramID.
The link is a partial right direction.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic *logic, const std::string &state)
std::string allowPredecessors(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< int > &fromLanes, const std::vector< int > &toLanes)
Definition: NBOwnTLDef.cpp:857
int getMaxIndex()
Returns the maximum index controlled by this traffic light.
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:1936
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
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:682
#define DEBUGCOND(PEDID)
void closeBuilding(bool checkVarDurations=true)
closes the building process
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
Definition: NBOwnTLDef.cpp:235
#define SUMOTime_MAX
Definition: SUMOTime.h:36
NBTrafficLightLogic * computeLogicAndConts(int brakingTimeSeconds, bool onlyConts=false)
helper function for myCompute
Definition: NBOwnTLDef.cpp:240
void collectLinks()
Collects the links participating in this traffic light.
Definition: NBOwnTLDef.cpp:730
static std::string addPedestrianPhases(NBTrafficLightLogic *logic, SUMOTime greenTime, SUMOTime minDur, SUMOTime maxDur, 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:651
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:35
bool corridorLike() const
test whether a joined tls with layout &#39;opposites&#39; would be built without dedicated left-turn phase ...
std::string allowSingleEdge(std::string state, const EdgeVector &fromEdges)
Definition: NBOwnTLDef.cpp:802
const NBNode * node
The parent node of this crossing.
Definition: NBNode.h:136
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
double getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
Definition: NBOwnTLDef.cpp:87
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:138
Represents a single node (junction) during network building.
Definition: NBNode.h:68
std::vector< Connection > getConnectionsFromLane(int lane, NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1127
A definition of a pedestrian crossing.
Definition: NBNode.h:132
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:1695
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
#define NUMERICAL_EPS
Definition: config.h:145
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:479
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:47
bool foes(const NBEdge *const from1, const NBEdge *const to1, const NBEdge *const from2, const NBEdge *const to2) const
Returns the information whether the given flows cross.
void initNeedsContRelation() const
Definition: NBOwnTLDef.cpp:758
Sorts edges by their priority within the node they end at.
Definition: NBOwnTLDef.h:265
NBConnectionVector myControlledLinks
The list of controlled links.
#define HEIGH_WEIGHT
Definition: NBOwnTLDef.cpp:40
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
int getToPrio(const NBEdge *const e)
Returns this edge&#39;s priority at the node it ends at.
Definition: NBOwnTLDef.cpp:81
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:748