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