Eclipse SUMO - Simulation of Urban MObility
NBLoadedSUMOTLDef.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2011-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 complete traffic light logic loaded from a sumo-net. (opted to reimplement
18 // since NBLoadedTLDef is quite vissim specific)
19 /****************************************************************************/
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <vector>
27 #include <set>
28 #include <cassert>
29 #include <iterator>
31 #include <utils/common/ToString.h>
33 #include "NBTrafficLightLogic.h"
34 #include "NBOwnTLDef.h"
36 #include "NBLoadedSUMOTLDef.h"
37 #include "NBNetBuilder.h"
38 #include "NBOwnTLDef.h"
39 #include "NBNode.h"
40 
41 //#define DEBUG_RECONSTRUCTION
42 
43 // ===========================================================================
44 // method definitions
45 // ===========================================================================
46 
47 NBLoadedSUMOTLDef::NBLoadedSUMOTLDef(const std::string& id, const std::string& programID,
48  SUMOTime offset, TrafficLightType type) :
49  NBTrafficLightDefinition(id, programID, offset, type),
50  myTLLogic(nullptr),
51  myReconstructAddedConnections(false),
52  myReconstructRemovedConnections(false),
53  myPhasesLoaded(false) {
54  myTLLogic = new NBTrafficLightLogic(id, programID, 0, offset, type);
55 }
56 
57 
59  // allow for adding a new program for the same def: take the offset and programID from the new logic
60  NBTrafficLightDefinition(def->getID(), logic->getProgramID(), logic->getOffset(), def->getType()),
61  myTLLogic(new NBTrafficLightLogic(logic)),
62  myOriginalNodes(def->getNodes().begin(), def->getNodes().end()),
65  myPhasesLoaded(false) {
66  assert(def->getType() == logic->getType());
68  myControlledNodes = def->getNodes();
69  NBLoadedSUMOTLDef* sumoDef = dynamic_cast<NBLoadedSUMOTLDef*>(def);
71  if (sumoDef != nullptr) {
74  }
75 }
76 
77 
79  delete myTLLogic;
80 }
81 
82 
84 NBLoadedSUMOTLDef::myCompute(int brakingTimeSeconds) {
85  // @todo what to do with those parameters?
86  UNUSED_PARAMETER(brakingTimeSeconds);
88  myTLLogic->closeBuilding(false);
91  return new NBTrafficLightLogic(myTLLogic);
92 }
93 
94 
95 void
96 NBLoadedSUMOTLDef::addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex, bool reconstruct) {
97  assert(myTLLogic->getNumLinks() > 0); // logic should be loaded by now
98  if (linkIndex >= (int)myTLLogic->getNumLinks()) {
99  throw ProcessError("Invalid linkIndex " + toString(linkIndex) + " for traffic light '" + getID() +
100  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
101  }
102  NBConnection conn(from, fromLane, to, toLane, linkIndex);
103  // avoid duplicates
104  auto newEnd = remove_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(conn));
105  // remove_if does not remove, only re-order
106  myControlledLinks.erase(newEnd, myControlledLinks.end());
107  myControlledLinks.push_back(conn);
108  addNode(from->getToNode());
109  addNode(to->getFromNode());
110  myOriginalNodes.insert(from->getToNode());
111  myOriginalNodes.insert(to->getFromNode());
112  // added connections are definitely controlled. make sure none are removed because they lie within the tl
113  // myControlledInnerEdges.insert(from->getID()); // @todo recheck: this appears to be obsolete
114  // set this information now so that it can be used while loading diffs
115  from->setControllingTLInformation(conn, getID());
116  myReconstructAddedConnections |= reconstruct;
117 }
118 
119 
120 void
126  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
127  (*i)->removeTrafficLight(&dummy);
128  }
129  }
131  return; // will be called again in reconstructLogic()
132  }
133  // if nodes have been removed our links may have been invalidated as well
134  // since no logic will be built anyway there is no reason to inform any edges
135  if (amInvalid()) {
136  return;
137  }
138  // set the information about the link's positions within the tl into the
139  // edges the links are starting at, respectively
140  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
141  const NBConnection& c = *it;
142  if (c.getTLIndex() >= (int)myTLLogic->getNumLinks()) {
143  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
144  "' with " + toString(myTLLogic->getNumLinks()) + " links.");
145  }
146  NBEdge* edge = c.getFrom();
147  if (edge != nullptr && edge->getNumLanes() > c.getFromLane()) {
148  // logic may have yet to be reconstructed
150  }
151  }
152 }
153 
154 
155 void
157 
158 
159 void
160 NBLoadedSUMOTLDef::replaceRemoved(NBEdge* removed, int removedLane, NBEdge* by, int byLane) {
161  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
162  (*it).replaceFrom(removed, removedLane, by, byLane);
163  (*it).replaceTo(removed, removedLane, by, byLane);
164  }
165 }
166 
167 
168 void
169 NBLoadedSUMOTLDef::addPhase(SUMOTime duration, const std::string& state, SUMOTime minDur, SUMOTime maxDur, const std::vector<int>& next, const std::string& name) {
170  myTLLogic->addStep(duration, state, minDur, maxDur, next, name);
171 }
172 
173 
174 bool
176  if (myControlledLinks.size() == 0) {
177  return true;
178  }
179  // make sure that myControlledNodes are the original nodes
180  if (myControlledNodes.size() != myOriginalNodes.size()) {
181  //std::cout << " myControlledNodes=" << myControlledNodes.size() << " myOriginalNodes=" << myOriginalNodes.size() << "\n";
182  return true;
183  }
184  if (myIncomingEdges.size() == 0) {
185  return true;
186  }
187  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
188  if (myOriginalNodes.count(*i) != 1) {
189  //std::cout << " node " << (*i)->getID() << " missing from myOriginalNodes\n";
190  return true;
191  }
192  }
193  return false;
194 }
195 
196 
197 void
198 NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
199  NBConnectionVector::iterator it = myControlledLinks.begin();
200  // find the connection but ignore its TLIndex since it might have been
201  // invalidated by an earlier removal
202  for (; it != myControlledLinks.end(); ++it) {
203  if (it->getFrom() == conn.getFrom() &&
204  it->getTo() == conn.getTo() &&
205  it->getFromLane() == conn.getFromLane() &&
206  it->getToLane() == conn.getToLane()) {
207  break;
208  }
209  }
210  if (it == myControlledLinks.end()) {
211  // a traffic light doesn't always controll all connections at a junction
212  // especially when using the option --tls.join
213  return;
214  }
215  myReconstructRemovedConnections |= reconstruct;
216 }
217 
218 
219 void
221  myOffset = offset;
222  myTLLogic->setOffset(offset);
223 }
224 
225 
226 void
228  myType = type;
229  myTLLogic->setType(type);
230 }
231 
232 
233 void
235  if (myControlledLinks.size() == 0) {
237  }
238  myIncomingEdges.clear();
239  EdgeVector myOutgoing;
240  // collect the edges from the participating nodes
241  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
242  const EdgeVector& incoming = (*i)->getIncomingEdges();
243  copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
244  const EdgeVector& outgoing = (*i)->getOutgoingEdges();
245  copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
246  }
247  // check which of the edges are completely within the junction
248  // and which are uncontrolled as well (we already know myControlledLinks)
249  for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) {
250  NBEdge* edge = *j;
251  // an edge lies within the logic if it is outgoing as well as incoming
252  EdgeVector::iterator k = std::find(myOutgoing.begin(), myOutgoing.end(), edge);
253  if (k != myOutgoing.end()) {
254  if (myControlledInnerEdges.count(edge->getID()) == 0) {
255  bool controlled = false;
256  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
257  if ((*it).getFrom() == edge) {
258  controlled = true;
259  break;
260  }
261  }
262  if (controlled) {
263  myControlledInnerEdges.insert(edge->getID());
264  } else {
265  myEdgesWithin.push_back(edge);
266  (*j)->setInsideTLS();
267  ++j; //j = myIncomingEdges.erase(j);
268  continue;
269  }
270  }
271  }
272  ++j;
273  }
274 }
275 
276 
277 void
279  if (myControlledLinks.size() == 0) {
280  // maybe we only loaded a different program for a default traffic light.
281  // Try to build links now.
282  myOriginalNodes.insert(myControlledNodes.begin(), myControlledNodes.end());
283  collectAllLinks();
284  }
285 }
286 
287 
289 void
290 NBLoadedSUMOTLDef::shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold) {
291  // avoid shifting twice if the edge is incoming and outgoing to a joined TLS
292  if (myShifted.count(edge) == 0) {
294  myShifted.insert(edge);
295  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
296  (*it).shiftLaneIndex(edge, offset, threshold);
297  }
298  }
299 }
300 
301 void
303  const int size = myTLLogic->getNumLinks();
304  int noLinksAll = 0;
305  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
306  const NBConnection& c = *it;
308  noLinksAll = MAX2(noLinksAll, (int)c.getTLIndex() + 1);
309  }
310  }
311  const int numNormalLinks = noLinksAll;
312  int oldCrossings = 0;
313  // collect crossings
314  bool customIndex = false;
315  std::vector<NBNode::Crossing*> crossings;
316  for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
317  const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
318  // set tl indices for crossings
319  customIndex |= (*i)->setCrossingTLIndices(getID(), noLinksAll);
320  copy(c.begin(), c.end(), std::back_inserter(crossings));
321  noLinksAll += (int)c.size();
322  oldCrossings += (*i)->numCrossingsFromSumoNet();
323  }
324  if ((int)crossings.size() != oldCrossings) {
325  std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
326  // do not rebuilt crossing states there are custom indices and the state string is long enough
327  if (phases.size() > 0 && (
328  (int)(phases.front().state.size()) < noLinksAll ||
329  ((int)(phases.front().state.size()) > noLinksAll && !customIndex))) {
330  // collect edges
331  EdgeVector fromEdges(size, (NBEdge*)nullptr);
332  EdgeVector toEdges(size, (NBEdge*)nullptr);
333  std::vector<int> fromLanes(size, 0);
334  collectEdgeVectors(fromEdges, toEdges, fromLanes);
335  const std::string crossingDefaultState(crossings.size(), 'r');
336 
337  // rebuild the logic (see NBOwnTLDef.cpp::myCompute)
339  SUMOTime brakingTime = TIME2STEPS(computeBrakingTime(OptionsCont::getOptions().getFloat("tls.yellow.min-decel")));
340  //std::cout << "patchIfCrossingsAdded for " << getID() << " numPhases=" << phases.size() << "\n";
341  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
342  const std::string state = it->state.substr(0, numNormalLinks) + crossingDefaultState;
343  NBOwnTLDef::addPedestrianPhases(newLogic, it->duration, it->minDur, it->maxDur, state, crossings, fromEdges, toEdges);
344  }
345  NBOwnTLDef::addPedestrianScramble(newLogic, noLinksAll, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
346 
347  delete myTLLogic;
348  myTLLogic = newLogic;
349  } else if (phases.size() == 0) {
350  WRITE_WARNING("Could not patch tlLogic '" + getID() + "' for changed crossings");
351  }
352  }
353 }
354 
355 
356 void
357 NBLoadedSUMOTLDef::collectEdgeVectors(EdgeVector& fromEdges, EdgeVector& toEdges, std::vector<int>& fromLanes) const {
358  assert(fromEdges.size() > 0);
359  assert(fromEdges.size() == toEdges.size());
360  const int size = (int)fromEdges.size();
361 
362  for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
363  const NBConnection& c = *it;
365  if (c.getTLIndex() >= size) {
366  throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
367  "' with " + toString(size) + " links.");
368  }
369  fromEdges[c.getTLIndex()] = c.getFrom();
370  toEdges[c.getTLIndex()] = c.getTo();
371  fromLanes[c.getTLIndex()] = c.getFromLane();
372  }
373  }
374 }
375 
376 
377 void
379  if (!amInvalid() && !myNeedsContRelationReady) {
380  myNeedsContRelation.clear();
381  myRightOnRedConflicts.clear();
382  const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
383  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
384  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
385  const std::string state = (*it).state;
386  for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
387  const NBConnection& c1 = *it1;
388  const int i1 = c1.getTLIndex();
389  if (i1 == NBConnection::InvalidTlIndex || (state[i1] != 'g' && state[i1] != 's') || c1.getFrom() == nullptr || c1.getTo() == nullptr) {
390  continue;
391  }
392  for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
393  const NBConnection& c2 = *it2;
394  const int i2 = c2.getTLIndex();
396  && i2 != i1
397  && (state[i2] == 'G' || state[i2] == 'g')
398  && c2.getFrom() != nullptr && c2.getTo() != nullptr) {
399  const bool rightTurnConflict = NBNode::rightTurnConflict(
400  c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
401  const bool forbidden = forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin);
402  const bool isFoes = foes(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo()) && !c2.getFrom()->isTurningDirectionAt(c2.getTo());
403  if (forbidden || rightTurnConflict) {
404  myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
405  }
406  if (isFoes) {
407  myRightOnRedConflicts.insert(std::make_pair(i1, i2));
408  }
409  //std::cout << getID() << " i1=" << i1 << " i2=" << i2 << " rightTurnConflict=" << rightTurnConflict << " forbidden=" << forbidden << " isFoes=" << isFoes << "\n";
410  }
411  }
412  }
413  }
414  }
417 }
418 
419 
420 bool
421 NBLoadedSUMOTLDef::rightOnRedConflict(int index, int foeIndex) const {
422  if (amInvalid()) {
423  return false;
424  }
428  }
429  return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
430 }
431 
432 
433 void
434 NBLoadedSUMOTLDef::registerModifications(bool addedConnections, bool removedConnections) {
435  myReconstructAddedConnections |= addedConnections;
436  myReconstructRemovedConnections |= removedConnections;
437 }
438 
439 void
441  const bool netedit = NBNetBuilder::runningNetedit();
442 #ifdef DEBUG_RECONSTRUCTION
444  std::cout << " reconstructLogic added=" << myReconstructAddedConnections << " removed=" << myReconstructRemovedConnections << " valid=" << hasValidIndices() << " oldLinks:\n";
445  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
446  std::cout << " " << *it << "\n";
447  }
448 #endif
451  // do not rebuild the logic when running netedit and all links are already covered by the program
452  if (!myPhasesLoaded && !(netedit && hasValidIndices())) {
453  // rebuild the logic from scratch
454  // XXX if a connection with the same from- and to-edge already exisits, its states could be copied instead
457  dummy.setProgramID(getProgramID());
462  for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
463  (*i)->removeTrafficLight(&dummy);
464  }
465  delete myTLLogic;
466  myTLLogic = newLogic;
467  if (newLogic != nullptr) {
468  newLogic->setID(getID());
469  newLogic->setType(getType());
470  newLogic->setOffset(getOffset());
472  // reset crossing custom indices
473  for (NBNode* n : myControlledNodes) {
474  for (NBNode::Crossing* c : n->getCrossings()) {
475  c->customTLIndex = NBConnection::InvalidTlIndex;
476  }
477  }
478 
479  }
480  } else {
482  }
483  }
486  // for each connection, check whether it is still valid
487  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end();) {
488  const NBConnection con = (*it);
489  if (// edge still exists
490  std::find(myIncomingEdges.begin(), myIncomingEdges.end(), con.getFrom()) != myIncomingEdges.end()
491  // connection still exists
492  && con.getFrom()->hasConnectionTo(con.getTo(), con.getToLane(), con.getFromLane())
493  // connection is still set to be controlled
494  && con.getFrom()->mayBeTLSControlled(con.getFromLane(), con.getTo(), con.getToLane())) {
495  it++;
496  } else {
497  // remove connection
498  const int removed = con.getTLIndex();
499  it = myControlledLinks.erase(it);
500  // no automatic modificaions when running netedit
501  if (!myPhasesLoaded && !(netedit && hasValidIndices())) {
502  // shift index off successive connections and remove entry from all phases if the tlIndex was only used by this connection
503  bool exclusive = true;
504  for (NBConnection& other : myControlledLinks) {
505  if (other != con && other.getTLIndex() == removed) {
506  exclusive = false;
507  break;
508  }
509  }
510  if (exclusive) {
511  // shift indices above the removed index downward
512  for (NBConnection& other : myControlledLinks) {
513  if (other.getTLIndex() > removed) {
514  other.setTLIndex(other.getTLIndex() - 1);
515  }
516  }
517  // shift crossing custom indices above the removed index downward
518  for (NBNode* n : myControlledNodes) {
519  for (NBNode::Crossing* c : n->getCrossings()) {
520  if (c->customTLIndex > removed) {
521  c->customTLIndex--;
522  }
523  }
524  }
525  // rebuild the logic
526  const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
528  for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
529  std::string newState = it->state;
530  newState.erase(newState.begin() + removed);
531  newLogic->addStep(it->duration, newState);
532  }
533  delete myTLLogic;
534  myTLLogic = newLogic;
535  }
536  }
537  }
538  }
540  }
541 #ifdef DEBUG_RECONSTRUCTION
542  if (debugPrintModified) {
543  std::cout << " newLinks:\n";
544  for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
545  std::cout << " " << *it << "\n";
546  }
547  }
548 #endif
549 }
550 
551 
552 int
554  int maxIndex = -1;
555  for (const NBConnection& c : myControlledLinks) {
556  maxIndex = MAX2(maxIndex, c.getTLIndex());
557  }
558  for (NBNode* n : myControlledNodes) {
559  for (NBNode::Crossing* c : n->getCrossings()) {
560  maxIndex = MAX2(maxIndex, c->tlLinkIndex);
561  maxIndex = MAX2(maxIndex, c->tlLinkIndex2);
562  }
563  }
564  return maxIndex;
565 }
566 
567 
568 int
570  return myTLLogic->getNumLinks() - 1;
571 }
572 
573 
574 bool
576  for (const NBConnection& c : myControlledLinks) {
577  if (c.getTLIndex() == NBConnection::InvalidTlIndex) {
578  return false;
579  }
580  }
581  for (NBNode* n : myControlledNodes) {
582  for (NBNode::Crossing* c : n->getCrossings()) {
583  if (c->tlLinkIndex == NBConnection::InvalidTlIndex) {
584  return false;
585  }
586  }
587  }
588  // method getMaxIndex() is const but cannot be declare as such due to inheritance
589  return const_cast<NBLoadedSUMOTLDef*>(this)->getMaxIndex() < myTLLogic->getNumLinks();
590 }
591 
592 
593 bool
595  const int maxIndex = getMaxIndex();
596  if (maxIndex >= 0 && maxIndex + 1 < myTLLogic->getNumLinks()) {
597  myTLLogic->setStateLength(maxIndex + 1);
598  return true;
599  }
600  return false;
601 }
602 
603 void
607  const int maxIndex = MAX2(getMaxIndex(), def->getMaxIndex());
608  myTLLogic->setStateLength(maxIndex + 1);
609  myControlledLinks.insert(myControlledLinks.end(), def->getControlledLinks().begin(), def->getControlledLinks().end());
610  myOriginalNodes.insert(def->getNodes().begin(), def->getNodes().end());
611 }
612 
613 bool
615  // count how often each index is used
616  std::map<int, int> indexUsage;
617  for (const NBConnection& c : myControlledLinks) {
618  indexUsage[c.getTLIndex()]++;
619  }
620  for (NBNode* n : myControlledNodes) {
621  for (NBNode::Crossing* c : n->getCrossings()) {
622  indexUsage[c->tlLinkIndex]++;
623  indexUsage[c->tlLinkIndex2]++;
624  }
625  }
626  for (auto it : indexUsage) {
627  if (it.first >= 0 && it.second > 1) {
628  return true;
629  }
630  }
631  return false;
632 }
633 
634 void
636  bool hasMinMaxDur = false;
637  for (auto phase : myTLLogic->getPhases()) {
638  if (phase.maxDur != UNSPECIFIED_DURATION) {
639  std::cout << " phase=" << phase.state << " maxDur=" << phase.maxDur << "\n";
640  hasMinMaxDur = true;
641  }
642  }
643  if (!hasMinMaxDur) {
644  const SUMOTime minMinDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.min-dur"));
645  const SUMOTime maxDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.max-dur"));
646  std::set<int> yellowIndices;
647  for (auto phase : myTLLogic->getPhases()) {
648  for (int i = 0; i < (int)phase.state.size(); i++) {
649  if (phase.state[i] == 'y' || phase.state[i] == 'Y') {
650  yellowIndices.insert(i);
651  }
652  }
653  }
654  for (int ip = 0; ip < (int)myTLLogic->getPhases().size(); ip++) {
655  bool needMinMaxDur = false;
656  auto phase = myTLLogic->getPhases()[ip];
657  std::set<int> greenIndices;
658  if (phase.state.find_first_of("yY") != std::string::npos) {
659  continue;
660  }
661  for (int i = 0; i < (int)phase.state.size(); i++) {
662  if (yellowIndices.count(i) != 0 && phase.state[i] == 'G') {
663  needMinMaxDur = true;
664  greenIndices.insert(i);
665  }
666  }
667  if (needMinMaxDur) {
668  double maxSpeed = 0;
669  for (NBConnection& c : myControlledLinks) {
670  if (greenIndices.count(c.getTLIndex()) != 0) {
671  maxSpeed = MAX2(maxSpeed, c.getFrom()->getLaneSpeed(c.getFromLane()));
672  }
673  }
674  // 5s at 50km/h, 10s at 80km/h, rounded to full seconds
675  const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
676  SUMOTime minDur = MAX2(minMinDur, TIME2STEPS(floor(minDurBySpeed + 0.5)));
677  myTLLogic->setPhaseMinDuration(ip, minDur);
678  myTLLogic->setPhaseMaxDuration(ip, maxDur);
679  }
680  }
681  }
682 }
683 /****************************************************************************/
684 
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
return true if certain connection must be controlled by TLS
Definition: NBEdge.cpp:2836
void removeConnection(const NBConnection &conn, bool reconstruct=true)
removes the given connection from the traffic light if recontruct=true, reconstructs the logic and in...
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
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
TrafficLightType myType
The algorithm type for the traffic light.
long long int SUMOTime
Definition: SUMOTime.h:35
virtual void addNode(NBNode *node)
Adds a node to the traffic light logic.
NBLoadedSUMOTLDef(const std::string &id, const std::string &programID, SUMOTime offset, TrafficLightType type)
Constructor.
void guessMinMaxDuration()
heuristically add minDur and maxDur when switching from tlType fixed to actuated
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
void collectEdges()
Build the list of participating edges.
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
static const std::string DummyID
id for temporary definitions
void setOffset(SUMOTime offset)
Sets the offset of this tls.
void reconstructLogic()
adapt to removal or addition of connections
int getNumLinks()
Returns the number of participating links.
A loaded (complete) traffic light logic.
RightOnRedConflicts myRightOnRedConflicts
A SUMO-compliant built logic for a traffic light.
bool myReconstructAddedConnections
whether the logic must be reconstructed
void registerModifications(bool addedConnections, bool removedConnections)
register changes that necessitate recomputation
EdgeVector myIncomingEdges
The list of incoming edges.
The representation of a single edge during network building.
Definition: NBEdge.h:86
TrafficLightType getType() const
get the algorithm type (static etc..)
class for identifying connections
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
const NBConnectionVector & getControlledLinks() const
returns the controlled links (depends on previous call to collectLinks)
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
The base class for traffic light logic definitions.
void setPhaseMinDuration(int phaseIndex, SUMOTime duration)
void setOffset(SUMOTime offset)
Sets the offset of this tls.
T MAX2(T a, T b)
Definition: StdDefs.h:80
static const SUMOTime UNSPECIFIED_DURATION
int computeBrakingTime(double minDecel) const
Computes the time vehicles may need to brake.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
bool hasValidIndices() const
return whether all tls link indices are valid
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
SUMOTime myOffset
The offset in the program.
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:32
void addPhase(SUMOTime duration, const std::string &state, SUMOTime minDur, SUMOTime maxDur, const std::vector< int > &next, const std::string &name)
Adds a phase to the logic the new phase is inserted at the end of the list of already added phases...
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
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
SUMOTime getOffset()
Returns the offset.
void setType(TrafficLightType type)
set the algorithm type (static etc..)
void initNeedsContRelation() const
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
virtual void collectEdges()
Build the list of participating edges.
static const int InvalidTlIndex
Definition: NBConnection.h:120
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
void updateParameter(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
virtual int getMaxIndex()=0
Returns the maximum index controlled by this traffic light and assigned to a connection.
std::set< std::string > myControlledInnerEdges
Set of inner edges that shall be controlled, though.
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 patchIfCrossingsAdded()
repair the plan if controlled nodes received pedestrian crossings
void addConnection(NBEdge *from, NBEdge *to, int fromLane, int toLane, int linkIndex, bool reconstruct=true)
Adds a connection and immediately informs the edges.
std::set< NBNode * > myOriginalNodes
The original nodes for which the loaded logic is valid.
bool hasConnectionTo(NBEdge *destEdge, int destLane, int fromLane=-1) const
Retrieves info about a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1170
const std::string & getID() const
Definition: NBEdge.h:1364
bool rightOnRedConflict(int index, int foeIndex) const
whether the given index must yield to the foeIndex while turing right on a red light ...
int getMaxValidIndex()
Returns the maximum index controlled by this traffic light.
void setProgramID(const std::string &programID)
Sets the programID.
const std::string & getProgramID() const
Returns the ProgramID.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
void joinLogic(NBTrafficLightDefinition *def)
join nodes and states from the given logic (append red state)
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
int getToLane() const
returns the to-lane
NBEdge * getTo() const
returns the to-edge (end of the connection)
void closeBuilding(bool checkVarDurations=true)
closes the building process
std::set< NBEdge * > myShifted
set of edges with shifted lane indices (to avoid shifting twice)
void setID(const std::string &newID)
resets the id
Definition: Named.h:85
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.
TrafficLightType getType() const
get the algorithm type (static etc..)
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
static bool runningNetedit()
whether netbuilding takes place in the context of NETEDIT
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
void collectLinks()
Collects the links participating in this traffic light (only if not previously loaded) ...
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2783
int getFromLane() const
returns the from-lane
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
Represents a single node (junction) during network building.
Definition: NBNode.h:68
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
A definition of a pedestrian crossing.
Definition: NBNode.h:132
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
~NBLoadedSUMOTLDef()
Destructor.
bool usingSignalGroups() const
whether this definition uses signal group (multiple connections with the same link index) ...
data structure for caching needsCont information
void setType(TrafficLightType type)
Sets the algorithm type of this tls.
void shiftTLConnectionLaneIndex(NBEdge *edge, int offset, int threshold=-1)
patches signal plans by modifying lane indices with the given offset, only indices with a value above...
int getTLIndex() const
returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled ...
Definition: NBConnection.h:94
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.
NBConnectionVector myControlledLinks
The list of controlled links.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
EdgeVector myEdgesWithin
The list of edges within the area controlled by the tls.
NBTrafficLightLogic * myTLLogic
phases are added directly to myTLLogic which is then returned in myCompute()
int getMaxIndex()
return the highest known tls link index used by any controlled connection or crossing ...
TrafficLightType
void collectEdgeVectors(EdgeVector &fromEdges, EdgeVector &toEdges, std::vector< int > &fromLanes) const
Collects the edges for each tlIndex.