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-2022 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
21// A traffic light logics which must be computed (only nodes/edges are given)
22/****************************************************************************/
23#include <config.h>
24
25#include <vector>
26#include <cassert>
27#include <iterator>
29#include "NBNode.h"
30#include "NBOwnTLDef.h"
31#include "NBTrafficLightLogic.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// static members
53// ===========================================================================
54const double NBOwnTLDef::MIN_SPEED_CROSSING_TIME(25 / 3.6);
55
56
57// ===========================================================================
58// member method definitions
59// ===========================================================================
60NBOwnTLDef::NBOwnTLDef(const std::string& id,
61 const std::vector<NBNode*>& junctions, SUMOTime offset,
62 TrafficLightType type) :
63 NBTrafficLightDefinition(id, junctions, DefaultProgramID, offset, type),
64 myHaveSinglePhase(false),
65 myLayout(TrafficLightLayout::DEFAULT) {
66}
67
68
69NBOwnTLDef::NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
70 TrafficLightType type) :
71 NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type),
72 myHaveSinglePhase(false),
73 myLayout(TrafficLightLayout::DEFAULT) {
74}
75
76
77NBOwnTLDef::NBOwnTLDef(const std::string& id, SUMOTime offset,
78 TrafficLightType type) :
79 NBTrafficLightDefinition(id, DefaultProgramID, offset, type),
80 myHaveSinglePhase(false),
81 myLayout(TrafficLightLayout::DEFAULT) {
82}
83
84
86
87
88int
90 return e->getJunctionPriority(e->getToNode());
91}
92
93
94double
96 switch (dir) {
100 return HEIGH_WEIGHT;
103 return LOW_WEIGHT;
104 default:
105 break;
106 }
107 return 0;
108}
109
110double
112 double val = 0;
113 for (int e1l = 0; e1l < e1->getNumLanes(); e1l++) {
114 std::vector<NBEdge::Connection> approached1 = e1->getConnectionsFromLane(e1l);
115 for (int e2l = 0; e2l < e2->getNumLanes(); e2l++) {
116 std::vector<NBEdge::Connection> approached2 = e2->getConnectionsFromLane(e2l);
117 for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
118 if (e1->getTurnDestination() == (*e1c).toEdge) {
119 continue;
120 }
121 for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
122 if (e2->getTurnDestination() == (*e2c).toEdge) {
123 continue;
124 }
125 const double sign = (forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge, true)
126 || forbids(e2, (*e2c).toEdge, e1, (*e1c).toEdge, true)) ? -1 : 1;
127 double w1;
128 double w2;
129 if (e1->getJunctionPriority(e1->getToNode()) == e2->getJunctionPriority(e2->getToNode())) {
130 w1 = getDirectionalWeight(e1->getToNode()->getDirection(e1, (*e1c).toEdge));
131 w2 = getDirectionalWeight(e2->getToNode()->getDirection(e2, (*e2c).toEdge));
132 } else {
133 if (e1->getJunctionPriority(e1->getToNode()) > e2->getJunctionPriority(e2->getToNode())) {
134 w1 = HEIGH_WEIGHT;
135 w2 = LOW_WEIGHT;
136 } else {
137 w1 = LOW_WEIGHT;
138 w2 = HEIGH_WEIGHT;
139 }
140 if (sign == -1) {
141 // extra penalty if edges with different junction priority are in conflict
142 w1 *= 2;
143 w2 *= 2;
144 }
145 }
146 val += sign * w1;
147 val += sign * w2;
148#ifdef DEBUG_STREAM_ORDERING
149 if (DEBUGCOND && DEBUGEDGE(e2) && DEBUGEDGE(e1)) {
150 std::cout << " sign=" << sign << " w1=" << w1 << " w2=" << w2 << " val=" << val
151 << " c1=" << (*e1c).getDescription(e1)
152 << " c2=" << (*e2c).getDescription(e2)
153 << "\n";
154 }
155#endif
156 }
157 }
158 }
159 }
160#ifdef DEBUG_STREAM_ORDERING
161 if (DEBUGCOND && DEBUGEDGE(e2) && DEBUGEDGE(e1)) {
162 std::cout << " computeUnblockedWeightedStreamNumber e1=" << e1->getID() << " e2=" << e2->getID() << " val=" << val << "\n";
163 }
164#endif
165 return val;
166}
167
168
169std::pair<NBEdge*, NBEdge*>
171 std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(nullptr), static_cast<NBEdge*>(nullptr));
172 double bestValue = -std::numeric_limits<double>::max();
173 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
174 for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
175 const double value = computeUnblockedWeightedStreamNumber(*i, *j);
176 if (value > bestValue) {
177 bestValue = value;
178 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
179 } else if (value == bestValue) {
180 const double ca = GeomHelper::getMinAngleDiff((*i)->getAngleAtNode((*i)->getToNode()), (*j)->getAngleAtNode((*j)->getToNode()));
181 const double oa = GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
182 if (fabs(oa - ca) < NUMERICAL_EPS) { // break ties by id
183 if (bestPair.first->getID() < (*i)->getID()) {
184 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
185 }
186 } else if (oa < ca) {
187 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
188 }
189 }
190 }
191 }
192 if (bestValue <= 0) {
193 // do not group edges
194 bestPair.second = nullptr;
195
196 }
197#ifdef DEBUG_STREAM_ORDERING
198 if (DEBUGCOND) {
199 std::cout << " getBestCombination bestValue=" << bestValue << " best=" << Named::getIDSecure(bestPair.first) << ", " << Named::getIDSecure(bestPair.second) << "\n";
200 }
201#endif
202 return bestPair;
203}
204
205
206std::pair<NBEdge*, NBEdge*>
208 if (incoming.size() == 1) {
209 // only one there - return the one
210 std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(), static_cast<NBEdge*>(nullptr));
211 incoming.clear();
212 return ret;
213 }
214 // determine the best combination
215 // by priority, first
216 EdgeVector used;
217 std::sort(incoming.begin(), incoming.end(), edge_by_incoming_priority_sorter());
218 used.push_back(*incoming.begin()); // the first will definitely be used
219 // get the ones with the same priority
220 int prio = getToPrio(*used.begin());
221 for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio == getToPrio(*i); ++i) {
222 used.push_back(*i);
223 }
224 // if there only lower priorised, use these, too
225 if (used.size() < 2) {
226 used = incoming;
227 }
228 std::pair<NBEdge*, NBEdge*> ret = getBestCombination(used);
229#ifdef DEBUG_STREAM_ORDERING
230 if (DEBUGCOND) {
231 std::cout << "getBestPair tls=" << getID() << " incoming=" << toString(incoming) << " prio=" << prio << " used=" << toString(used) << " best=" << Named::getIDSecure(ret.first) << ", " << Named::getIDSecure(ret.second) << "\n";
232 }
233#endif
234
235 incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
236 if (ret.second != nullptr) {
237 incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
238 }
239 return ret;
240}
241
242bool
244 for (const NBEdge::Connection& c : fromEdge->getConnections()) {
245 LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, c.toEdge);
246 if (dir == LinkDirection::STRAIGHT) {
247 return true;
248 }
249 }
250 return false;
251}
252
254NBOwnTLDef::myCompute(int brakingTimeSeconds) {
255 return computeLogicAndConts(brakingTimeSeconds);
256}
257
258
260NBOwnTLDef::computeLogicAndConts(int brakingTimeSeconds, bool onlyConts) {
261 myNeedsContRelation.clear();
262 myRightOnRedConflicts.clear();
263 const bool isNEMA = myType == TrafficLightType::NEMA;
264 const SUMOTime brakingTime = TIME2STEPS(brakingTimeSeconds);
265 const SUMOTime leftTurnTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.left-green.time"));
268 const SUMOTime earliestEnd = UNSPECIFIED_DURATION;
269 const SUMOTime latestEnd = UNSPECIFIED_DURATION;
270
271 // things collect for NEMA phase building
272 std::vector<std::pair<NBEdge*, NBEdge*> > chosenList;
273 std::vector<std::string> straightStates;
274 std::vector<std::string> leftStates;
275
276 // build complete lists first
277 const EdgeVector& incoming = getIncomingEdges();
278 EdgeVector fromEdges, toEdges;
279 std::vector<bool> isTurnaround;
280 std::vector<bool> hasTurnLane;
281 std::vector<int> fromLanes;
282 std::vector<int> toLanes;
283 std::vector<SUMOTime> crossingTime;
284 int totalNumLinks = 0;
285 for (NBEdge* const fromEdge : incoming) {
286 const int numLanes = fromEdge->getNumLanes();
287 const bool edgeHasStraight = hasStraightConnection(fromEdge);
288 for (int i2 = 0; i2 < numLanes; i2++) {
289 bool hasLeft = false;
290 bool hasPartLeft = false;
291 bool hasStraight = false;
292 bool hasRight = false;
293 bool hasTurnaround = false;
294 for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
295 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
296 continue;
297 }
298 fromEdges.push_back(fromEdge);
299 fromLanes.push_back(i2);
300 toLanes.push_back(approached.toLane);
301 toEdges.push_back(approached.toEdge);
302 if (approached.vmax < NUMERICAL_EPS || (fromEdge->getPermissions() & SVC_PASSENGER) == 0
303 || (approached.toEdge->getPermissions() & SVC_PASSENGER) == 0) {
304 crossingTime.push_back(0);
305 } else {
306 crossingTime.push_back(TIME2STEPS((approached.length + approached.viaLength) / MAX2(approached.vmax, MIN_SPEED_CROSSING_TIME)));
307 }
308 // std::cout << fromEdge->getID() << " " << approached.toEdge->getID() << " " << (fromEdge->getPermissions() & SVC_PASSENGER) << " " << approached.length << " " << approached.viaLength << " " << approached.vmax << " " << crossingTime.back() << std::endl;
309 if (approached.toEdge != nullptr) {
310 isTurnaround.push_back(fromEdge->isTurningDirectionAt(approached.toEdge));
311 } else {
312 isTurnaround.push_back(true);
313 }
314 LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, approached.toEdge);
315 if (dir == LinkDirection::STRAIGHT) {
316 hasStraight = true;
317 } else if (dir == LinkDirection::RIGHT || dir == LinkDirection::PARTRIGHT) {
318 hasRight = true;
319 } else if (dir == LinkDirection::LEFT) {
320 hasLeft = true;
321 } else if (dir == LinkDirection::PARTLEFT) {
322 hasPartLeft = true;
323 } else if (dir == LinkDirection::TURN) {
324 hasTurnaround = true;
325 }
326 totalNumLinks++;
327 }
328 for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
329 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
330 continue;
331 }
332 hasTurnLane.push_back(
333 (hasLeft && !hasPartLeft && !hasStraight && !hasRight)
334 || (hasPartLeft && !hasLeft && !hasStraight && !hasRight)
335 || (hasPartLeft && hasLeft && edgeHasStraight && !hasRight)
336 || (!hasLeft && !hasPartLeft && !hasTurnaround && hasRight));
337 }
338 //std::cout << " from=" << fromEdge->getID() << "_" << i2 << " hasTurnLane=" << hasTurnLane.back() << " s=" << hasStraight << " l=" << hasLeft << " r=" << hasRight << " t=" << hasTurnaround << "\n";
339 }
340 }
341 // collect crossings
342 std::vector<NBNode::Crossing*> crossings;
343 for (NBNode* const node : myControlledNodes) {
344 const std::vector<NBNode::Crossing*>& c = node->getCrossings();
345 if (!onlyConts) {
346 // set tl indices for crossings
347 node->setCrossingTLIndices(getID(), totalNumLinks);
348 }
349 copy(c.begin(), c.end(), std::back_inserter(crossings));
350 totalNumLinks += (int)c.size();
351 }
352
353 NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), totalNumLinks, myOffset, myType);
354 EdgeVector toProc = getConnectedOuterEdges(incoming);
355 const SUMOTime greenTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.green.time"));
356 SUMOTime allRedTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.allred.time"));
357 const double minorLeftSpeedThreshold = OptionsCont::getOptions().getFloat("tls.minor-left.max-speed");
358 const bool noMixed = OptionsCont::getOptions().getBool("tls.no-mixed");
359 // left-turn phases do not work well for joined tls, so we build incoming instead
361 // @note this prevents updating after loading plain-xml into netedit computing tls and then changing the default layout
363 }
364 const bool groupOpposites = (myLayout == TrafficLightLayout::OPPOSITES && (myControlledNodes.size() <= 2 || corridorLike()));
365
366 // build all phases
367 std::vector<int> greenPhases; // indices of green phases
368 std::vector<bool> hadGreenMajor(totalNumLinks, false);
369 while (toProc.size() > 0) {
370 bool groupTram = false;
371 bool groupOther = false;
372 std::pair<NBEdge*, NBEdge*> chosen;
373 if (groupOpposites) {
374 if (incoming.size() == 2) {
375 // if there are only 2 incoming edges we need to decide whether they are a crossing or a "continuation"
376 // @node: this heuristic could be extended to also check the number of outgoing edges
377 double angle = fabs(NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
378 // angle would be 180 for straight opposing incoming edges
379 if (angle < 135) {
380 chosen = std::pair<NBEdge*, NBEdge*>(toProc[0], static_cast<NBEdge*>(nullptr));
381 toProc.erase(toProc.begin());
382 } else {
383 chosen = getBestPair(toProc);
384 }
385 } else {
386 chosen = getBestPair(toProc);
387 if (chosen.second == nullptr && chosen.first->getPermissions() == SVC_TRAM) {
388 groupTram = true;
389 for (auto it = toProc.begin(); it != toProc.end();) {
390 if ((*it)->getPermissions() == SVC_TRAM) {
391 it = toProc.erase(it);
392 } else {
393 it++;
394 }
395 }
396 }
397 }
398 } else {
399 NBEdge* chosenEdge = toProc[0];
400 chosen = std::pair<NBEdge*, NBEdge*>(chosenEdge, static_cast<NBEdge*>(nullptr));
401 toProc.erase(toProc.begin());
402 SVCPermissions perms = chosenEdge->getPermissions();
403 if (perms == SVC_TRAM) {
404 groupTram = true;
405 } else if ((perms & ~(SVC_PEDESTRIAN | SVC_BICYCLE | SVC_DELIVERY)) == 0) {
406 groupOther = true;
407 }
408 // group all edges with the same permissions into a single phase (later)
409 if (groupTram || groupOther) {
410 for (auto it = toProc.begin(); it != toProc.end();) {
411 if ((*it)->getPermissions() == perms) {
412 it = toProc.erase(it);
413 } else {
414 it++;
415 }
416 }
417 }
418 }
419 int pos = 0;
420 std::string state(totalNumLinks, 'r');
421#ifdef DEBUG_PHASES
422 if (DEBUGCOND) {
423 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";
424 }
425#endif
426 chosenList.push_back(chosen);
427 // plain straight movers
428 double maxSpeed = 0;
429 bool haveGreen = false;
430 for (const NBEdge* const fromEdge : incoming) {
431 const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second; //chosen.find(fromEdge)!=chosen.end();
432 const int numLanes = fromEdge->getNumLanes();
433 for (int i2 = 0; i2 < numLanes; i2++) {
434 for (const NBEdge::Connection& approached : fromEdge->getConnectionsFromLane(i2)) {
435 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
436 continue;
437 }
438 if (inChosen) {
439 state[pos] = 'G';
440 haveGreen = true;
441 maxSpeed = MAX2(maxSpeed, fromEdge->getSpeed());
442 } else {
443 state[pos] = 'r';
444 }
445 ++pos;
446 }
447 }
448 }
449 if (!haveGreen) {
450 continue;
451 }
452
453#ifdef DEBUG_PHASES
454 if (DEBUGCOND) {
455 std::cout << " state after plain straight movers " << state << "\n";
456 }
457#endif
458 if (!isNEMA) {
459 // correct behaviour for those that are not in chosen, but may drive, though
460 state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
461 if (groupTram) {
462 state = allowByVClass(state, fromEdges, toEdges, SVC_TRAM);
463 } else if (groupOther) {
464 state = allowByVClass(state, fromEdges, toEdges, SVC_PEDESTRIAN | SVC_BICYCLE | SVC_DELIVERY);
465 }
466#ifdef DEBUG_PHASES
467 if (DEBUGCOND) {
468 std::cout << " state after grouping by vClass " << state << "\n";
469 }
470#endif
471 if (groupOpposites || chosen.first->getToNode()->getType() == SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED) {
472 state = allowUnrelated(state, fromEdges, toEdges, isTurnaround, crossings);
473 }
474#ifdef DEBUG_PHASES
475 if (DEBUGCOND) {
476 std::cout << " state after finding allowUnrelated " << state << "\n";
477 }
478#endif
479 }
480 // correct behaviour for those that have to wait (mainly left-mover)
481 bool haveForbiddenLeftMover = false;
482 std::vector<bool> rightTurnConflicts(pos, false);
483 std::vector<bool> mergeConflicts(pos, false);
484 state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
485 for (int i1 = 0; i1 < pos; ++i1) {
486 if (state[i1] == 'G') {
487 hadGreenMajor[i1] = true;
488 }
489 }
490#ifdef DEBUG_PHASES
491 if (DEBUGCOND) {
492 std::cout << " state after correcting left movers=" << state << "\n";
493 }
494#endif
495
496 std::vector<bool> leftGreen(pos, false);
497 // check whether at least one left-turn lane exist
498 bool foundLeftTurnLane = false;
499 for (int i1 = 0; i1 < pos; ++i1) {
500 if (state[i1] == 'g' && !rightTurnConflicts[i1] && !mergeConflicts[i1] && hasTurnLane[i1]) {
501 foundLeftTurnLane = true;
502 }
503 }
504 const bool buildLeftGreenPhase = (haveForbiddenLeftMover && !myHaveSinglePhase && leftTurnTime > 0 && foundLeftTurnLane
505 && groupOpposites && !groupTram && !groupOther);
506
507 // find indices for exclusive left green phase and apply option minor-left.max-speed
508 for (int i1 = 0; i1 < pos; ++i1) {
509 if (state[i1] == 'g' && !rightTurnConflicts[i1] && !mergeConflicts[i1]
510 // only activate turn-around together with a real left-turn
511 && (!isTurnaround[i1] || (i1 > 0 && leftGreen[i1 - 1]))) {
512 leftGreen[i1] = true;
513 if (fromEdges[i1]->getSpeed() > minorLeftSpeedThreshold) {
514 if (buildLeftGreenPhase) {
515 state[i1] = 'r';
516 //std::cout << " disabling minorLeft " << i1 << " (speed=" << fromEdges[i1]->getSpeed() << " thresh=" << minorLeftSpeedThreshold << ")\n";
517 } else if (!isTurnaround[i1]) {
518 WRITE_WARNINGF(TL("Minor green from edge '%' to edge '%' exceeds %m/s. Maybe a left-turn lane is missing."),
519 fromEdges[i1]->getID(), toEdges[i1]->getID(), minorLeftSpeedThreshold);
520 }
521 }
522 }
523 }
524
525#ifdef DEBUG_PHASES
526 if (DEBUGCOND) {
527 std::cout << getID() << " state=" << state << " buildLeft=" << buildLeftGreenPhase << " hFLM=" << haveForbiddenLeftMover << " turnLane=" << foundLeftTurnLane
528 << " \nrtC=" << toString(rightTurnConflicts)
529 << " \nmC=" << toString(mergeConflicts)
530 << " \nhTL=" << toString(hasTurnLane)
531 << " \nlGr=" << toString(leftGreen)
532 << "\n";
533 }
534#endif
535 straightStates.push_back(state);
536
537 const std::string vehicleState = state; // backup state before pedestrian modifications
538 greenPhases.push_back((int)logic->getPhases().size());
539
540 // 5s at 50km/h, 10s at 80km/h, rounded to full seconds
541 const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
542 SUMOTime minDur = MAX2(minMinDur, TIME2STEPS(floor(minDurBySpeed + 0.5)));
543 if (chosen.first->getPermissions() == SVC_TRAM && (chosen.second == nullptr || chosen.second->getPermissions() == SVC_TRAM)) {
544 // shorter minDuration for tram phase (only if the phase is
545 // exclusively for tram)
546 bool tramExclusive = true;
547 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
548 if (state[i1] == 'G') {
549 SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
550 if (linkPerm != SVC_TRAM) {
551 tramExclusive = false;
552 break;
553 }
554 }
555 }
556 if (tramExclusive) {
557 // one tram per actuated phase
558 minDur = TIME2STEPS(1);
559 }
560 }
561
562 state = addPedestrianPhases(logic, greenTime, minDur, maxDur, earliestEnd, latestEnd, state, crossings, fromEdges, toEdges);
563 // pedestrians have 'r' from here on
564 for (int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
565 state[i1] = 'r';
566 }
567 if (brakingTime > 0) {
568 SUMOTime maxCross = 0;
569 // build yellow (straight)
570 for (int i1 = 0; i1 < pos; ++i1) {
571 if (state[i1] != 'G' && state[i1] != 'g') {
572 continue;
573 }
574 if ((vehicleState[i1] >= 'a' && vehicleState[i1] <= 'z')
575 && buildLeftGreenPhase
576 && !rightTurnConflicts[i1]
577 && !mergeConflicts[i1]
578 && leftGreen[i1]) {
579 continue;
580 }
581 state[i1] = 'y';
582 maxCross = MAX2(maxCross, crossingTime[i1]);
583 }
584 // add step
585 logic->addStep(brakingTime, state);
586 // add optional all-red state
587 if (!buildLeftGreenPhase) {
589 allRedTime = computeEscapeTime(state, fromEdges, toEdges);
590 }
591 buildAllRedState(allRedTime + MAX2(0ll, maxCross - brakingTime - allRedTime), logic, state);
592 }
593 }
594
595
596 if (buildLeftGreenPhase) {
597 // build left green
598 for (int i1 = 0; i1 < pos; ++i1) {
599 if (state[i1] == 'Y' || state[i1] == 'y') {
600 state[i1] = 'r';
601 continue;
602 }
603 if (leftGreen[i1]) {
604 state[i1] = 'G';
605 }
606 }
607 leftStates.push_back(state);
608 state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
609 state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
610 bool buildMixedGreenPhase = false;
611 std::vector<bool> mixedGreen(pos, false);
612 const std::string oldState = state;
613 if (noMixed) {
614 state = correctMixed(state, fromEdges, fromLanes, buildMixedGreenPhase, mixedGreen);
615 }
616 if (state != oldState) {
617 for (int i1 = 0; i1 < pos; ++i1) {
618 if (mixedGreen[i1]) {
619 // patch previous yellow and allred phase
620 int yellowIndex = (int)logic->getPhases().size() - 1;
621 if (allRedTime > 0) {
622 logic->setPhaseState(yellowIndex--, i1, LINKSTATE_TL_RED);
623 }
624 if (brakingTime > 0) {
625 logic->setPhaseState(yellowIndex, i1, LINKSTATE_TL_YELLOW_MINOR);
626 }
627 }
628 }
629 state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
630 }
631
632 // add step
633 logic->addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
634
635 // build left yellow
636 if (brakingTime > 0) {
637 SUMOTime maxCross = 0;
638 for (int i1 = 0; i1 < pos; ++i1) {
639 if (state[i1] != 'G' && state[i1] != 'g') {
640 continue;
641 }
642 state[i1] = 'y';
643 maxCross = MAX2(maxCross, crossingTime[i1]);
644 }
645 // add step
646 logic->addStep(brakingTime, state);
647 // add optional all-red state
648 buildAllRedState(allRedTime + MAX2(0ll, maxCross - brakingTime - allRedTime), logic, state);
649 }
650
651 if (buildMixedGreenPhase) {
652 // build mixed green
653 // @todo if there is no left green phase we might want to build two
654 // mixed-green phases but then we should consider avoid a common
655 // opposite phase for this direction
656
657 for (int i1 = 0; i1 < pos; ++i1) {
658 if (state[i1] == 'Y' || state[i1] == 'y') {
659 state[i1] = 'r';
660 continue;
661 }
662 if (mixedGreen[i1]) {
663 state[i1] = 'G';
664 }
665 }
666 state = allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
667 state = correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
668
669 // add step
670 logic->addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
671
672 // build mixed yellow
673 if (brakingTime > 0) {
674 SUMOTime maxCross = 0;
675 for (int i1 = 0; i1 < pos; ++i1) {
676 if (state[i1] != 'G' && state[i1] != 'g') {
677 continue;
678 }
679 state[i1] = 'y';
680 maxCross = MAX2(maxCross, crossingTime[i1]);
681 }
682 // add step
683 logic->addStep(brakingTime, state);
684 // add optional all-red state
685 buildAllRedState(allRedTime + MAX2(0ll, maxCross - brakingTime - allRedTime), logic, state);
686 }
687 }
688
689 } else if (isNEMA) {
690 std::string& s = straightStates.back();
691 std::string leftState = s;
692 for (int ii = 0; ii < pos; ++ii) {
693 if (s[ii] != 'r') {
694 NBEdge* fromEdge = fromEdges[ii];
695 NBEdge* toEdge = toEdges[ii];
696 LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, toEdge);
697 if (hasTurnLane[ii] && (dir == LinkDirection::LEFT || dir == LinkDirection::TURN)) {
698 s[ii] = 'r';
699 leftState[ii] = 'G';
700 } else {
701 leftState[ii] = 'r';
702 }
703 }
704 }
705 leftStates.push_back(leftState);
706 }
707 }
708 // fix pedestrian crossings that did not get the green light yet
709 if (crossings.size() > 0) {
710 addPedestrianScramble(logic, totalNumLinks, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
711 }
712 // add optional red phase if there were no foes
713 if (logic->getPhases().size() == 2 && brakingTime > 0
714 && OptionsCont::getOptions().getInt("tls.red.time") > 0) {
715 const SUMOTime redTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.red.time"));
716 logic->addStep(redTime, std::string(totalNumLinks, 'r'));
717 }
718 // fix states to account for custom crossing link indices
719 if (crossings.size() > 0 && !onlyConts) {
721 }
722
724 // exiting the oneway section should always be possible
725 deactivateInsideEdges(logic, fromEdges);
726 }
727 if (isNEMA) {
728 NBTrafficLightLogic* nemaLogic = buildNemaPhases(fromEdges, chosenList, straightStates, leftStates);
729 if (nemaLogic == nullptr) {
730 WRITE_WARNINGF(TL("Generating NEMA phases is not support for traffic light '%' with % incoming edges. Using tlType 'actuated' as fallback"), getID(), incoming.size());
733 } else {
734 delete logic;
735 logic = nemaLogic;
736 }
737 }
738
739 SUMOTime totalDuration = logic->getDuration();
740
741 if ((OptionsCont::getOptions().isDefault("tls.green.time") || !OptionsCont::getOptions().isDefault("tls.cycle.time")) && !isNEMA) {
742 const SUMOTime cycleTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.cycle.time"));
743 // adapt to cycle time by changing the duration of the green phases
744 SUMOTime minGreenDuration = SUMOTime_MAX;
745 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
746 const SUMOTime dur = logic->getPhases()[*it].duration;
747 minGreenDuration = MIN2(minGreenDuration, dur);
748 }
749 const int patchSeconds = (int)(STEPS2TIME(cycleTime - totalDuration) / (double)greenPhases.size());
750 const int patchSecondsRest = (int)(STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (int)greenPhases.size();
751 //std::cout << "cT=" << cycleTime << " td=" << totalDuration << " pS=" << patchSeconds << " pSR=" << patchSecondsRest << "\n";
752 if (STEPS2TIME(minGreenDuration) + patchSeconds < MIN_GREEN_TIME
753 || STEPS2TIME(minGreenDuration) + patchSeconds + patchSecondsRest < MIN_GREEN_TIME
754 || greenPhases.size() == 0) {
755 if (getID() != DummyID) {
756 WRITE_WARNINGF(TL("The traffic light '%' cannot be adapted to a cycle time of %."), getID(), time2string(cycleTime));
757 }
758 // @todo use a multiple of cycleTime ?
759 } else {
760 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
761 logic->setPhaseDuration(*it, logic->getPhases()[*it].duration + TIME2STEPS(patchSeconds));
762 }
763 if (greenPhases.size() > 0) {
764 logic->setPhaseDuration(greenPhases.front(), logic->getPhases()[greenPhases.front()].duration + TIME2STEPS(patchSecondsRest));
765 }
766 totalDuration = logic->getDuration();
767 }
768 }
769
771 // this computation only makes sense for single nodes
773 if (totalDuration > 0) {
774 if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime) && !isNEMA) {
775 WRITE_WARNINGF(TL("The traffic light '%' has a high cycle time of %."), getID(), time2string(totalDuration));
776 }
777 logic->closeBuilding();
778 return logic;
779 } else {
780 delete logic;
781 return nullptr;
782 }
783}
784
785
786bool
787NBOwnTLDef::hasCrossing(const NBEdge* from, const NBEdge* to, const std::vector<NBNode::Crossing*>& crossings) {
788 assert(to != 0);
789 for (auto c : crossings) {
790 const NBNode::Crossing& cross = *c;
791 // only check connections at this crossings node
792 if (to->getFromNode() == cross.node) {
793 for (EdgeVector::const_iterator it_e = cross.edges.begin(); it_e != cross.edges.end(); ++it_e) {
794 const NBEdge* edge = *it_e;
795 if (edge == from || edge == to) {
796 return true;
797 }
798 }
799 }
800 }
801 return false;
802}
803
804
805std::string
806NBOwnTLDef::addPedestrianPhases(NBTrafficLightLogic* logic, const SUMOTime greenTime, const SUMOTime minDur, const SUMOTime maxDur,
807 const SUMOTime earliestEnd, const SUMOTime latestEnd,
808 std::string state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
809 // compute based on length of the crossing if not set by the user
810 const SUMOTime pedClearingTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-clearance.time"));
811 // compute if not set by user: must be able to reach the middle of the second "Richtungsfahrbahn"
812 const SUMOTime minPedTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-min.time"));
813 const std::string orig = state;
814 state = patchStateForCrossings(state, crossings, fromEdges, toEdges);
815 if (orig == state) {
816 // add step
817 logic->addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
818 } else {
819 const SUMOTime pedTime = greenTime - pedClearingTime;
820 if (pedTime >= minPedTime) {
821 // ensure clearing time for pedestrians
822 const int pedStates = (int)crossings.size();
823 logic->addStep(pedTime, state, minDur, maxDur, earliestEnd, latestEnd);
824 state = state.substr(0, state.size() - pedStates) + std::string(pedStates, 'r');
825 logic->addStep(pedClearingTime, state);
826 } else {
827 state = orig;
828 // not safe for pedestrians.
829 logic->addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
830 }
831 }
832 return state;
833}
834
835
836std::string
837NBOwnTLDef::patchStateForCrossings(const std::string& state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
838 std::string result = state;
839 const int pos = (int)(state.size() - crossings.size()); // number of controlled vehicle links
840 for (int ic = 0; ic < (int)crossings.size(); ++ic) {
841 const int i1 = pos + ic;
842 const NBNode::Crossing& cross = *crossings[ic];
843 bool isForbidden = false;
844 for (int i2 = 0; i2 < pos && !isForbidden; ++i2) {
845 // only check connections at this crossings node
846 if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.node) {
847 for (EdgeVector::const_iterator it = cross.edges.begin(); it != cross.edges.end(); ++it) {
848 const NBEdge* edge = *it;
849 const LinkDirection i2dir = cross.node->getDirection(fromEdges[i2], toEdges[i2]);
850 if (state[i2] != 'r' && state[i2] != 's' && (edge == fromEdges[i2] ||
851 (edge == toEdges[i2] && (i2dir == LinkDirection::STRAIGHT || i2dir == LinkDirection::PARTLEFT || i2dir == LinkDirection::PARTRIGHT)))) {
852 isForbidden = true;
853 break;
854 }
855 }
856 }
857 }
858 if (!isForbidden) {
859 result[i1] = 'G';
860 } else {
861 result[i1] = 'r';
862 }
863 }
864
865 // correct behaviour for roads that are in conflict with a pedestrian crossing
866 for (int i1 = 0; i1 < pos; ++i1) {
867 if (result[i1] == 'G') {
868 for (int ic = 0; ic < (int)crossings.size(); ++ic) {
869 const NBNode::Crossing& crossing = *crossings[ic];
870 if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.node) {
871 const int i2 = pos + ic;
872 if (result[i2] == 'G' && crossing.node->mustBrakeForCrossing(fromEdges[i1], toEdges[i1], crossing)) {
873 result[i1] = 'g';
874 break;
875 }
876 }
877 }
878 }
879 }
880 return result;
881}
882
883
884void
886 myControlledLinks.clear();
888}
889
890
891void
893 // set the information about the link's positions within the tl into the
894 // edges the links are starting at, respectively
895 for (NBConnectionVector::const_iterator j = myControlledLinks.begin(); j != myControlledLinks.end(); ++j) {
896 const NBConnection& conn = *j;
897 NBEdge* edge = conn.getFrom();
898 edge->setControllingTLInformation(conn, getID());
899 }
900}
901
902
903void
904NBOwnTLDef::remapRemoved(NBEdge* /*removed*/, const EdgeVector& /*incoming*/,
905 const EdgeVector& /*outgoing*/) {}
906
907
908void
909NBOwnTLDef::replaceRemoved(NBEdge* /*removed*/, int /*removedLane*/,
910 NBEdge* /*by*/, int /*byLane*/, bool /*incoming*/) {}
911
912
913void
916 if (myControlledNodes.size() > 0) {
917 // we use a dummy node just to maintain const-correctness
918 myNeedsContRelation.clear();
921 NBTrafficLightLogic* tllDummy = dummy.computeLogicAndConts(0, true);
922 delete tllDummy;
924 for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
925 (*i)->removeTrafficLight(&dummy);
926 }
927 }
929 }
930}
931
932
935 EdgeVector result = incoming;
936 for (EdgeVector::iterator it = result.begin(); it != result.end();) {
937 if ((*it)->getConnections().size() == 0 || (*it)->isInsideTLS()) {
938 it = result.erase(it);
939 } else {
940 ++it;
941 }
942 }
943 return result;
944}
945
946
947std::string
948NBOwnTLDef::allowCompatible(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
949 const std::vector<int>& fromLanes, const std::vector<int>& toLanes) {
950 state = allowSingleEdge(state, fromEdges);
951 state = allowFollowers(state, fromEdges, toEdges);
952 state = allowPredecessors(state, fromEdges, toEdges, fromLanes, toLanes);
953 return state;
954}
955
956
957std::string
958NBOwnTLDef::allowSingleEdge(std::string state, const EdgeVector& fromEdges) {
959 // if only one edge has green, ensure sure that all connections from that edge are green
960 const int size = (int)fromEdges.size();
961 NBEdge* greenEdge = nullptr;
962 for (int i1 = 0; i1 < size; ++i1) {
963 if (state[i1] == 'G') {
964 if (greenEdge == nullptr) {
965 greenEdge = fromEdges[i1];
966 } else if (greenEdge != fromEdges[i1]) {
967 return state;
968 }
969 }
970 }
971 if (greenEdge != nullptr) {
972 for (int i1 = 0; i1 < size; ++i1) {
973 if (fromEdges[i1] == greenEdge) {
974 state[i1] = 'G';
975 }
976 }
977 }
978 return state;
979}
980
981
982std::string
983NBOwnTLDef::allowFollowers(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
984 // check continuation within joined traffic lights
985 bool check = true;
986 while (check) {
987 check = false;
988 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
989 if (state[i1] == 'G') {
990 continue;
991 }
992 //if (forbidden(state, i1, fromEdges, toEdges)) {
993 // continue;
994 //}
995 bool followsChosen = false;
996 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
997 if (state[i2] == 'G' && fromEdges[i1] == toEdges[i2]) {
998 followsChosen = true;
999 break;
1000 }
1001 }
1002 if (followsChosen) {
1003 state[i1] = 'G';
1004 check = true;
1005 }
1006 }
1007 }
1008 return state;
1009}
1010
1011
1012std::string
1013NBOwnTLDef::allowPredecessors(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
1014 const std::vector<int>& fromLanes, const std::vector<int>& toLanes) {
1015 // also allow predecessors of chosen edges if the lanes match and there is no conflict
1016 // (must be done after the followers are done because followers are less specific)
1017 bool check = true;
1018 while (check) {
1019 check = false;
1020 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1021 if (state[i1] == 'G') {
1022 continue;
1023 }
1024 if (forbidden(state, i1, fromEdges, toEdges)) {
1025 continue;
1026 }
1027 bool preceedsChosen = false;
1028 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1029 if (state[i2] == 'G' && fromEdges[i2] == toEdges[i1]
1030 && fromLanes[i2] == toLanes[i1]) {
1031 preceedsChosen = true;
1032 break;
1033 }
1034 }
1035 if (preceedsChosen) {
1036 state[i1] = 'G';
1037 check = true;
1038 }
1039 }
1040 }
1041 return state;
1042}
1043
1044
1045std::string
1046NBOwnTLDef::allowUnrelated(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
1047 const std::vector<bool>& isTurnaround,
1048 const std::vector<NBNode::Crossing*>& crossings) {
1049 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1050 if (state[i1] == 'G') {
1051 continue;
1052 }
1053 bool isForbidden = false;
1054 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1055 if (state[i2] == 'G' && !isTurnaround[i2] &&
1056 (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) || forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
1057 isForbidden = true;
1058 break;
1059 }
1060 }
1061 if (!isForbidden && !hasCrossing(fromEdges[i1], toEdges[i1], crossings)) {
1062 state[i1] = 'G';
1063 }
1064 }
1065 return state;
1066}
1067
1068
1069std::string
1070NBOwnTLDef::allowByVClass(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges, SVCPermissions perm) {
1071 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1072 SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
1073 if ((linkPerm & ~perm) == 0) {
1074 state[i1] = 'G';
1075 }
1076 }
1077 return state;
1078}
1079
1080
1081bool
1082NBOwnTLDef::forbidden(const std::string& state, int index, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
1083 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1084 if (state[i2] == 'G' && foes(fromEdges[i2], toEdges[i2], fromEdges[index], toEdges[index])) {
1085 return true;
1086 }
1087 }
1088 return false;
1089}
1090
1091
1092std::string
1093NBOwnTLDef::correctConflicting(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
1094 const std::vector<bool>& isTurnaround,
1095 const std::vector<int>& fromLanes,
1096 const std::vector<int>& toLanes,
1097 const std::vector<bool>& hadGreenMajor,
1098 bool& haveForbiddenLeftMover,
1099 std::vector<bool>& rightTurnConflicts,
1100 std::vector<bool>& mergeConflicts) {
1101 const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
1102 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1103 if (state[i1] == 'G') {
1104 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1105 if ((state[i2] == 'G' || state[i2] == 'g')) {
1107 fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
1108 rightTurnConflicts[i1] = true;
1109 }
1110 if (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true, controlledWithin) || rightTurnConflicts[i1]) {
1111 state[i1] = 'g';
1112 myNeedsContRelation.insert(StreamPair(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2]));
1113 if (!isTurnaround[i1] && !hadGreenMajor[i1] && !rightTurnConflicts[i1]) {
1114 haveForbiddenLeftMover = true;
1115 }
1116 } else if (fromEdges[i1] == fromEdges[i2]
1117 && fromLanes[i1] != fromLanes[i2]
1118 && toEdges[i1] == toEdges[i2]
1119 && toLanes[i1] == toLanes[i2]
1120 && fromEdges[i1]->getToNode()->mergeConflictYields(fromEdges[i1], fromLanes[i1], fromLanes[i2], toEdges[i1], toLanes[i1])) {
1121 mergeConflicts[i1] = true;
1122 state[i1] = 'g';
1123 }
1124 }
1125 }
1126 }
1127 if (state[i1] == 'r') {
1128 if (fromEdges[i1]->getToNode()->getType() == SumoXMLNodeType::TRAFFIC_LIGHT_RIGHT_ON_RED &&
1129 fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) == LinkDirection::RIGHT) {
1130 state[i1] = 's';
1131 // do not allow right-on-red when in conflict with exclusive left-turn phase
1132 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1133 if (state[i2] == 'G' && !isTurnaround[i2] &&
1134 (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) ||
1135 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
1136 const LinkDirection foeDir = fromEdges[i2]->getToNode()->getDirection(fromEdges[i2], toEdges[i2]);
1137 if (foeDir == LinkDirection::LEFT || foeDir == LinkDirection::PARTLEFT) {
1138 state[i1] = 'r';
1139 break;
1140 }
1141 }
1142 }
1143 if (state[i1] == 's') {
1144 // handle right-on-red conflicts
1145 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1146 if (state[i2] == 'G' && !isTurnaround[i2] &&
1147 (forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1], true) ||
1148 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2], true))) {
1149 myRightOnRedConflicts.insert(std::make_pair(i1, i2));
1150 }
1151 }
1152 }
1153 }
1154 }
1155 }
1156 return state;
1157}
1158
1159
1160std::string
1161NBOwnTLDef::correctMixed(std::string state, const EdgeVector& fromEdges,
1162 const std::vector<int>& fromLanes,
1163 bool& buildMixedGreenPhase, std::vector<bool>& mixedGreen) {
1164 for (int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1165 if ((state[i1] == 'G' || state[i1] == 'g')) {
1166 for (int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1167 if (i1 != i2 && fromEdges[i1] == fromEdges[i2] && fromLanes[i1] == fromLanes[i2]
1168 && state[i2] != 'G' && state[i2] != 'g') {
1169 state[i1] = state[i2];
1170 //std::cout << " mixedGreen i1=" << i1 << " i2=" << i2 << "\n";
1171 mixedGreen[i1] = true;
1172 if (fromEdges[i1]->getNumLanesThatAllow(SVC_PASSENGER) > 1) {
1173 buildMixedGreenPhase = true;
1174 }
1175 }
1176 }
1177 }
1178 }
1179 return state;
1180}
1181
1182
1183void
1184NBOwnTLDef::addPedestrianScramble(NBTrafficLightLogic* logic, int totalNumLinks, SUMOTime /* greenTime */, SUMOTime brakingTime,
1185 const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges) {
1186 const int vehLinks = totalNumLinks - (int)crossings.size();
1187 std::vector<bool> foundGreen(crossings.size(), false);
1188 const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->getPhases();
1189 for (int i = 0; i < (int)phases.size(); i++) {
1190 const std::string state = phases[i].state;
1191 for (int j = 0; j < (int)crossings.size(); j++) {
1192 LinkState ls = (LinkState)state[vehLinks + j];
1194 foundGreen[j] = true;
1195 }
1196 }
1197 }
1198 for (int j = 0; j < (int)foundGreen.size(); j++) {
1199 if (!foundGreen[j]) {
1200 // add a phase where all pedestrians may walk, (preceded by a yellow phase and followed by a clearing phase)
1201 if (phases.size() > 0) {
1202 bool needYellowPhase = false;
1203 std::string state = phases.back().state;
1204 for (int i1 = 0; i1 < vehLinks; ++i1) {
1205 if (state[i1] == 'G' || state[i1] == 'g') {
1206 state[i1] = 'y';
1207 needYellowPhase = true;
1208 }
1209 }
1210 // add yellow step
1211 if (needYellowPhase && brakingTime > 0) {
1212 logic->addStep(brakingTime, state);
1213 }
1214 }
1215 const SUMOTime pedClearingTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.crossing-clearance.time"));
1216 const SUMOTime scrambleTime = TIME2STEPS(OptionsCont::getOptions().getInt("tls.scramble.time"));
1217 addPedestrianPhases(logic, scrambleTime + pedClearingTime, UNSPECIFIED_DURATION,
1218 UNSPECIFIED_DURATION, UNSPECIFIED_DURATION, UNSPECIFIED_DURATION, std::string(totalNumLinks, 'r'), crossings, fromEdges, toEdges);
1219 break;
1220 }
1221 }
1222}
1223
1224
1225void
1226NBOwnTLDef::buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic* logic, const std::string& state) {
1227 if (allRedTime > 0) {
1228 // build all-red phase
1229 std::string allRedState = state;
1230 for (int i = 0; i < (int)state.size(); i++) {
1231 if (allRedState[i] == 'Y' || allRedState[i] == 'y') {
1232 allRedState[i] = 'r';
1233 }
1234 }
1235 logic->addStep(TIME2STEPS(ceil(STEPS2TIME(allRedTime))), allRedState);
1236 }
1237}
1238
1239
1240void
1242 int minCustomIndex = -1;
1243 int maxCustomIndex = -1;
1244 // collect crossings
1245 for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
1246 const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
1247 for (auto crossing : c) {
1248 minCustomIndex = MIN2(minCustomIndex, crossing->customTLIndex);
1249 minCustomIndex = MIN2(minCustomIndex, crossing->customTLIndex2);
1250 maxCustomIndex = MAX2(maxCustomIndex, crossing->customTLIndex);
1251 maxCustomIndex = MAX2(maxCustomIndex, crossing->customTLIndex2);
1252 }
1253 }
1254 // custom crossing linkIndex could lead to longer states. ensure that every index has a state
1255 if (maxCustomIndex >= logic->getNumLinks()) {
1256 logic->setStateLength(maxCustomIndex + 1);
1257 }
1258 // XXX shorter state vectors are possible as well
1259 // XXX if the indices are shuffled the guessed crossing states should be shuffled correspondingly
1260 // XXX initialize the backward index to the same state as the forward index
1261}
1262
1263void
1265 // assume that yellow states last at most one phase
1266 const int n = logic->getNumLinks();
1267 const int p = (int)logic->getPhases().size();
1268 for (int i1 = 0; i1 < n; ++i1) {
1269 LinkState prev = (LinkState)logic->getPhases().back().state[i1];
1270 for (int i2 = 0; i2 < p; ++i2) {
1271 LinkState cur = (LinkState)logic->getPhases()[i2].state[i1];
1272 LinkState next = (LinkState)logic->getPhases()[(i2 + 1) % p].state[i1];
1273 if (cur == LINKSTATE_TL_YELLOW_MINOR
1275 && next == LINKSTATE_TL_GREEN_MAJOR) {
1276 logic->setPhaseState(i2, i1, prev);
1277 }
1278 prev = cur;
1279 }
1280 }
1281}
1282
1283
1284void
1286 const int n = logic->getNumLinks();
1287 std::vector<bool> alwaysGreen(n, true);
1288 for (int i1 = 0; i1 < n; ++i1) {
1289 for (const auto& phase : logic->getPhases()) {
1290 if (phase.state[i1] != 'G') {
1291 alwaysGreen[i1] = false;
1292 break;
1293 }
1294 }
1295 }
1296 const int p = (int)logic->getPhases().size();
1297 for (int i1 = 0; i1 < n; ++i1) {
1298 if (alwaysGreen[i1]) {
1299 for (int i2 = 0; i2 < p; ++i2) {
1301 }
1302 }
1303 }
1304}
1305
1306
1307void
1309 const int n = logic->getNumLinks();
1310 const int p = (int)logic->getPhases().size();
1311 for (int i1 = 0; i1 < n; ++i1) {
1312 if (fromEdges[i1]->isInsideTLS()) {
1313 for (int i2 = 0; i2 < p; ++i2) {
1315 }
1316 }
1317 }
1318}
1319
1320
1322NBOwnTLDef::computeEscapeTime(const std::string& state, const EdgeVector& fromEdges, const EdgeVector& toEdges) const {
1323 const int n = (int)state.size();
1324 double maxTime = 0;
1325 for (int i1 = 0; i1 < n; ++i1) {
1326 if (state[i1] == 'y' && !fromEdges[i1]->isInsideTLS()) {
1327 for (int i2 = 0; i2 < n; ++i2) {
1328 if (fromEdges[i2]->isInsideTLS()) {
1329 double gapSpeed = (toEdges[i1]->getSpeed() + fromEdges[i2]->getSpeed()) / 2;
1330 double time = fromEdges[i1]->getGeometry().back().distanceTo2D(fromEdges[i2]->getGeometry().back()) / gapSpeed;
1331 maxTime = MAX2(maxTime, time);
1332 }
1333 }
1334 }
1335 }
1336 // give some slack
1337 return TIME2STEPS(floor(maxTime * 1.2 + 5));
1338}
1339
1340
1341int
1345 if (logic != nullptr) {
1346 return logic->getNumLinks() - 1;
1347 } else {
1348 return -1;
1349 }
1350}
1351
1352
1353bool
1355 if (getID() == DummyID) {
1356 // avoid infinite recursion
1357 return true;
1358 }
1359 assert(myControlledNodes.size() >= 2);
1362 NBTrafficLightLogic* tllDummy = dummy.computeLogicAndConts(0, true);
1363 int greenPhases = 0;
1364 for (const auto& phase : tllDummy->getPhases()) {
1365 if (phase.state.find_first_of("gG") != std::string::npos) {
1366 greenPhases++;
1367 }
1368 }
1369 delete tllDummy;
1370 for (const auto& controlledNode : myControlledNodes) {
1371 controlledNode->removeTrafficLight(&dummy);
1372 }
1373 return greenPhases <= 2;
1374}
1375
1376
1379 const EdgeVector& fromEdges,
1380 const std::vector<std::pair<NBEdge*, NBEdge*> >& chosenList,
1381 const std::vector<std::string>& straightStates,
1382 const std::vector<std::string>& leftStates) {
1383 if (chosenList.size() != 2) {
1384 return nullptr;
1385 }
1386 const SUMOTime dur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.cycle.time"));
1387 const SUMOTime vehExt = TIME2STEPS(OptionsCont::getOptions().getInt("tls.nema.vehExt"));
1388 const SUMOTime yellow = TIME2STEPS(OptionsCont::getOptions().getInt("tls.nema.yellow"));
1389 const SUMOTime red = TIME2STEPS(OptionsCont::getOptions().getInt("tls.nema.red"));
1390 const SUMOTime minMinDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.min-dur"));
1391 const SUMOTime maxDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.max-dur"));
1392 const SUMOTime earliestEnd = UNSPECIFIED_DURATION;
1393 const SUMOTime latestEnd = UNSPECIFIED_DURATION;
1394
1395 const int totalNumLinks = (int)straightStates[0].size();
1396 NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), totalNumLinks, myOffset, myType);
1397 std::vector<int> ring1({1, 2, 3, 4});
1398 std::vector<int> ring2({5, 6, 7, 8});
1399 std::vector<int> barrier1({4, 8});
1400 std::vector<int> barrier2({2, 6});
1401 int phaseNameLeft = 1;
1402 for (int i = 0; i < (int)chosenList.size(); i++) {
1403 NBEdge* e1 = chosenList[i].first;
1404 assert(e1 != nullptr);
1405 NBEdge* e2 = chosenList[i].second;
1406 if (i < (int)leftStates.size()) {
1407 std::string left1 = filterState(leftStates[i], fromEdges, e1);
1408 if (left1 != "") {
1409 logic->addStep(dur, left1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, toString(phaseNameLeft));
1410 }
1411 }
1412 if (e2 != nullptr) {
1413 std::string straight2 = filterState(straightStates[i], fromEdges, e2);
1414 logic->addStep(dur, straight2, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, toString(phaseNameLeft + 1));
1415 if (i < (int)leftStates.size()) {
1416 std::string left2 = filterState(leftStates[i], fromEdges, e2);
1417 if (left2 != "") {
1418 logic->addStep(dur, left2, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, toString(phaseNameLeft + 4));
1419 }
1420 }
1421
1422 }
1423 std::string straight1 = filterState(straightStates[i], fromEdges, e1);
1424 if (straight1 == "") {
1425 delete logic;
1426 return nullptr;
1427 }
1428 logic->addStep(dur, straight1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red, toString(phaseNameLeft + 5));
1429 phaseNameLeft += 2;
1430 }
1431 std::map<int, int> names; // nema phase name -> sumo phase index
1432 for (int i = 0; i < (int)logic->getPhases().size(); i++) {
1433 names[StringUtils::toInt(logic->getPhases()[i].name)] = i;
1434 }
1435
1436 filterMissingNames(ring1, names, false);
1437 filterMissingNames(ring2, names, false);
1438 filterMissingNames(barrier1, names, true);
1439 filterMissingNames(barrier2, names, true);
1440 if (ring1[2] == 0 && ring1[3] == 0) {
1441 ring1[3] = 8;
1442 }
1443 fixDurationSum(logic, names, ring1[0], ring1[1], ring2[0], ring2[1]);
1444 fixDurationSum(logic, names, ring1[2], ring1[3], ring2[2], ring2[3]);
1445
1446 logic->setParameter("ring1", joinToString(ring1, ","));
1447 logic->setParameter("ring2", joinToString(ring2, ","));
1448 logic->setParameter("barrierPhases", joinToString(barrier1, ","));
1449 logic->setParameter("barrier2Phases", joinToString(barrier2, ","));
1450 return logic;
1451}
1452
1453
1454std::string
1455NBOwnTLDef::filterState(std::string state, const EdgeVector& fromEdges, const NBEdge* e) {
1456 bool haveGreen = false;
1457 for (int j = 0; j < (int)state.size(); j++) {
1458 if (fromEdges[j] != e) {
1459 state[j] = 'r';
1460 } else if (state[j] != 'r') {
1461 haveGreen = true;
1462 }
1463 }
1464 if (haveGreen) {
1465 return state;
1466 } else {
1467 return "";
1468 }
1469}
1470
1471void
1472NBOwnTLDef::filterMissingNames(std::vector<int>& vec, const std::map<int, int>& names, bool isBarrier) {
1473 for (int i = 0; i < (int)vec.size(); i++) {
1474 if (names.count(vec[i]) == 0) {
1475 if (isBarrier) {
1476 if (names.count(vec[i] - 1) > 0) {
1477 vec[i] = vec[i] - 1;
1478 } else {
1479 vec[i] = 8;
1480 }
1481 } else {
1482 vec[i] = 0;
1483 }
1484 }
1485 }
1486}
1487
1488void
1489NBOwnTLDef::fixDurationSum(NBTrafficLightLogic* logic, const std::map<int, int>& names, int ring1a, int ring1b, int ring2a, int ring2b) {
1490 std::set<int> ring1existing;
1491 std::set<int> ring2existing;
1492 if (names.count(ring1a) != 0) {
1493 ring1existing.insert(ring1a);
1494 }
1495 if (names.count(ring1b) != 0) {
1496 ring1existing.insert(ring1b);
1497 }
1498 if (names.count(ring2a) != 0) {
1499 ring2existing.insert(ring2a);
1500 }
1501 if (names.count(ring2b) != 0) {
1502 ring2existing.insert(ring2b);
1503 }
1504 if (ring1existing.size() > 0 && ring2existing.size() > 0 &&
1505 ring1existing.size() != ring2existing.size()) {
1506 int pI; // sumo phase index
1507 if (ring1existing.size() < ring2existing.size()) {
1508 pI = names.find(*ring1existing.begin())->second;
1509 } else {
1510 pI = names.find(*ring2existing.begin())->second;
1511 }
1512 const auto& p = logic->getPhases()[pI];
1513 SUMOTime newMaxDur = 2 * p.maxDur + p.yellow + p.red;
1514 logic->setPhaseMaxDuration(pI, newMaxDur);
1515 }
1516}
1517
1518/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
@ DEFAULT
default cursor
#define DEBUGCOND(PEDID)
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:266
#define TL(string)
Definition: MsgHandler.h:282
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:42
#define MIN_GREEN_TIME
Definition: NBOwnTLDef.cpp:42
#define HEIGH_WEIGHT
Definition: NBOwnTLDef.cpp:39
#define LOW_WEIGHT
Definition: NBOwnTLDef.cpp:40
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
#define STEPS2TIME(x)
Definition: SUMOTime.h:54
#define SUMOTime_MAX
Definition: SUMOTime.h:33
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_DELIVERY
vehicle is a small delivery vehicle
@ SVC_TRAM
vehicle is a light rail
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
TrafficLightType
TrafficLightLayout
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)....
@ PARTLEFT
The link is a partial left direction.
@ RIGHT
The link is a (hard) right direction.
@ TURN
The link is a 180 degree turn.
@ LEFT
The link is a (hard) left direction.
@ STRAIGHT
The link is a straight direction.
@ PARTRIGHT
The link is a partial right direction.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_TL_YELLOW_MINOR
The link has yellow light, has to brake anyway.
@ LINKSTATE_TL_RED
The link has red light (must brake)
@ LINKSTATE_TL_GREEN_MINOR
The link has green light, has to brake.
@ LINKSTATE_TL_OFF_NOSIGNAL
The link is controlled by a tls which is off, not blinking, may pass.
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:282
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:173
NBEdge * getFrom() const
returns the from-edge (start of the connection)
The representation of a single edge during network building.
Definition: NBEdge.h:92
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4137
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:1043
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:552
const std::string & getID() const
Definition: NBEdge.h:1526
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
Definition: NBEdge.cpp:3492
std::vector< Connection > getConnectionsFromLane(int lane, NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
Definition: NBEdge.cpp:1241
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:526
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:2057
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:545
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3767
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:45
A definition of a pedestrian crossing.
Definition: NBNode.h:129
const NBNode * node
The parent node of this crossing.
Definition: NBNode.h:134
EdgeVector edges
The edges being crossed.
Definition: NBNode.h:136
Represents a single node (junction) during network building.
Definition: NBNode.h:66
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:2229
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
Definition: NBNode.cpp:1933
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:1914
Sorts edges by their priority within the node they end at.
Definition: NBOwnTLDef.h:310
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
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
void fixSuperfluousYellow(NBTrafficLightLogic *logic) const
avoid yellow signal between successive green (major) phases
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< int > &toLanes, const std::vector< bool > &hadGreenMajor, bool &haveForbiddenLeftMover, std::vector< bool > &rightTurnConflicts, std::vector< bool > &mergeConflicts)
change 'G' to 'g' for conflicting connections
void checkCustomCrossingIndices(NBTrafficLightLogic *logic) const
fix states in regard to custom crossing indices
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:837
std::string allowByVClass(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, SVCPermissions perm)
int getMaxIndex()
Returns the maximum index controlled by this traffic light.
bool myHaveSinglePhase
Whether left-mover should not have an additional phase.
Definition: NBOwnTLDef.h:327
bool corridorLike() const
test whether a joined tls with layout 'opposites' would be built without dedicated left-turn phase
SUMOTime computeEscapeTime(const std::string &state, const EdgeVector &fromEdges, const EdgeVector &toEdges) const
compute time to clear all vehicles from within an alternateOneWay layout
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces a removed edge/lane.
Definition: NBOwnTLDef.cpp:909
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
Definition: NBOwnTLDef.cpp:207
~NBOwnTLDef()
Destructor.
Definition: NBOwnTLDef.cpp:85
void collectLinks()
Collects the links participating in this traffic light.
Definition: NBOwnTLDef.cpp:885
void deactivateAlwaysGreen(NBTrafficLightLogic *logic) const
switch of signal for links that are always green
NBTrafficLightLogic * computeLogicAndConts(int brakingTimeSeconds, bool onlyConts=false)
helper function for myCompute
Definition: NBOwnTLDef.cpp:260
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:787
std::string allowPredecessors(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< int > &fromLanes, const std::vector< int > &toLanes)
void deactivateInsideEdges(NBTrafficLightLogic *logic, const EdgeVector &fromEdges) const
switch of signal for links that are inside a joined tls
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:111
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:904
int getToPrio(const NBEdge *const e)
Returns this edge's priority at the node it ends at.
Definition: NBOwnTLDef.cpp:89
NBTrafficLightLogic * buildNemaPhases(const EdgeVector &fromEdges, const std::vector< std::pair< NBEdge *, NBEdge * > > &chosenList, const std::vector< std::string > &straightStates, const std::vector< std::string > &leftStates)
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:948
std::string correctMixed(std::string state, const EdgeVector &fromEdges, const std::vector< int > &fromLanes, bool &buildMixedGreenPhase, std::vector< bool > &mixedGreen)
prevent green and red from the same lane
void fixDurationSum(NBTrafficLightLogic *logic, const std::map< int, int > &names, int ring1a, int ring1b, int ring2a, int ring2b)
ensure that phase max durations before each barrier have the same sum in both rings
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
Definition: NBOwnTLDef.cpp:254
std::string filterState(std::string state, const EdgeVector &fromEdges, const NBEdge *e)
mask out all greens that do not originate at the given edge
std::string allowFollowers(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges)
Definition: NBOwnTLDef.cpp:983
void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic *logic, const std::string &state)
double getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
Definition: NBOwnTLDef.cpp:95
std::string allowSingleEdge(std::string state, const EdgeVector &fromEdges)
Definition: NBOwnTLDef.cpp:958
bool hasStraightConnection(const NBEdge *fromEdge)
check whether there is a straight connection from this edge
Definition: NBOwnTLDef.cpp:243
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:170
void initNeedsContRelation() const
Definition: NBOwnTLDef.cpp:914
static void addPedestrianScramble(NBTrafficLightLogic *logic, int totalNumLinks, 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
NBOwnTLDef(const std::string &id, const std::vector< NBNode * > &junctions, SUMOTime offset, TrafficLightType type)
Constructor.
Definition: NBOwnTLDef.cpp:60
static EdgeVector getConnectedOuterEdges(const EdgeVector &incoming)
get edges that have connections
Definition: NBOwnTLDef.cpp:934
void filterMissingNames(std::vector< int > &vec, const std::map< int, int > &names, bool isBarrier)
keep only valid NEMA phase names (for params)
TrafficLightLayout myLayout
the layout for generated signal plans
Definition: NBOwnTLDef.h:330
static std::string addPedestrianPhases(NBTrafficLightLogic *logic, const SUMOTime greenTime, const SUMOTime minDur, const SUMOTime maxDur, const SUMOTime earliestEnd, const SUMOTime latestEnd, 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:806
std::string allowUnrelated(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< bool > &isTurnaround, const std::vector< NBNode::Crossing * > &crossings)
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
Definition: NBOwnTLDef.cpp:892
static const double MIN_SPEED_CROSSING_TIME
minimum speed for computing time to cross intersection
Definition: NBOwnTLDef.h:143
The base class for traffic light logic definitions.
const std::string & getProgramID() const
Returns the ProgramID.
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
RightOnRedConflicts myRightOnRedConflicts
TrafficLightType myType
The algorithm type for the traffic light.
static const std::string DummyID
id for temporary definitions
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.
NBTrafficLightLogic * compute(OptionsCont &oc)
Computes the traffic light logic.
NBConnectionVector myControlledLinks
The list of controlled links.
virtual void setType(TrafficLightType type)
set the algorithm type (static etc..)
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
void collectAllLinks(NBConnectionVector &into)
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
SUMOTime myOffset
The offset in the program.
static const SUMOTime UNSPECIFIED_DURATION
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.
A SUMO-compliant built logic for a traffic light.
SUMOTime getDuration() const
Returns the duration of the complete cycle.
void closeBuilding(bool checkVarDurations=true)
closes the building process
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
void setPhaseState(int phaseIndex, int tlIndex, LinkState linkState)
Modifies the state for an existing phase (used by NETEDIT)
void setPhaseMaxDuration(int phaseIndex, SUMOTime duration)
Modifies the max duration for an existing phase (used by NETEDIT)
int getNumLinks()
Returns the number of participating links.
void setType(TrafficLightType type)
set the algorithm type (static etc..)
void setStateLength(int numLinks, LinkState fill=LINKSTATE_TL_RED)
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
void addStep(const SUMOTime duration, const std::string &state, const std::vector< int > &next=std::vector< int >(), const std::string &name="", const int index=-1)
Adds a phase to the logic (static)
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:67
const std::string & getID() const
Returns the id.
Definition: Named.h:74
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
static StringBijection< TrafficLightLayout > TrafficLightLayouts
traffic light layouts
T get(const std::string &str) const
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:201
data structure for caching needsCont information