42#define MIN_GREEN_TIME 5
61 const std::vector<NBNode*>& junctions,
SUMOTime offset,
64 myHaveSinglePhase(false),
72 myHaveSinglePhase(false),
80 myHaveSinglePhase(false),
113 for (
int e1l = 0; e1l < e1->
getNumLanes(); e1l++) {
115 for (
int e2l = 0; e2l < e2->
getNumLanes(); e2l++) {
117 for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
121 for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
125 const double sign = (
forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge,
true)
126 ||
forbids(e2, (*e2c).toEdge, e1, (*e1c).toEdge,
true)) ? -1 : 1;
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)
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";
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) {
176 if (value > bestValue) {
178 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
179 }
else if (value == bestValue) {
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) {
183 if (bestPair.first->getID() < (*i)->getID()) {
184 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
186 }
else if (oa < ca) {
187 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
192 if (bestValue <= 0) {
194 bestPair.second =
nullptr;
197#ifdef DEBUG_STREAM_ORDERING
206std::pair<NBEdge*, NBEdge*>
208 if (incoming.size() == 1) {
210 std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(),
static_cast<NBEdge*
>(
nullptr));
218 used.push_back(*incoming.begin());
221 for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio ==
getToPrio(*i); ++i) {
225 if (used.size() < 2) {
229#ifdef DEBUG_STREAM_ORDERING
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));
272 std::vector<std::pair<NBEdge*, NBEdge*> > chosenList;
273 std::vector<std::string> straightStates;
274 std::vector<std::string> leftStates;
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();
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;
295 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
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);
309 if (approached.toEdge !=
nullptr) {
310 isTurnaround.push_back(fromEdge->isTurningDirectionAt(approached.toEdge));
312 isTurnaround.push_back(
true);
314 LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, approached.toEdge);
324 hasTurnaround =
true;
329 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
332 hasTurnLane.push_back(
333 (hasLeft && !hasPartLeft && !hasStraight && !hasRight)
334 || (hasPartLeft && !hasLeft && !hasStraight && !hasRight)
335 || (hasPartLeft && hasLeft && edgeHasStraight && !hasRight)
336 || (!hasLeft && !hasPartLeft && !hasTurnaround && hasRight));
342 std::vector<NBNode::Crossing*> crossings;
344 const std::vector<NBNode::Crossing*>& c = node->getCrossings();
347 node->setCrossingTLIndices(
getID(), totalNumLinks);
349 copy(c.begin(), c.end(), std::back_inserter(crossings));
350 totalNumLinks += (int)c.size();
367 std::vector<int> greenPhases;
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) {
377 double angle = fabs(
NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
380 chosen = std::pair<NBEdge*, NBEdge*>(toProc[0],
static_cast<NBEdge*
>(
nullptr));
381 toProc.erase(toProc.begin());
387 if (chosen.second ==
nullptr && chosen.first->getPermissions() ==
SVC_TRAM) {
389 for (
auto it = toProc.begin(); it != toProc.end();) {
390 if ((*it)->getPermissions() ==
SVC_TRAM) {
391 it = toProc.erase(it);
399 NBEdge* chosenEdge = toProc[0];
400 chosen = std::pair<NBEdge*, NBEdge*>(chosenEdge,
static_cast<NBEdge*
>(
nullptr));
401 toProc.erase(toProc.begin());
409 if (groupTram || groupOther) {
410 for (
auto it = toProc.begin(); it != toProc.end();) {
411 if ((*it)->getPermissions() == perms) {
412 it = toProc.erase(it);
420 std::string state(totalNumLinks,
'r');
426 chosenList.push_back(chosen);
429 bool haveGreen =
false;
430 for (
const NBEdge*
const fromEdge : incoming) {
431 const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second;
432 const int numLanes = fromEdge->getNumLanes();
433 for (
int i2 = 0; i2 < numLanes; i2++) {
435 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
441 maxSpeed =
MAX2(maxSpeed, fromEdge->getSpeed());
455 std::cout <<
" state after plain straight movers " << state <<
"\n";
460 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
463 }
else if (groupOther) {
468 std::cout <<
" state after grouping by vClass " << state <<
"\n";
472 state =
allowUnrelated(state, fromEdges, toEdges, isTurnaround, crossings);
476 std::cout <<
" state after finding allowUnrelated " << state <<
"\n";
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;
492 std::cout <<
" state after correcting left movers=" << state <<
"\n";
496 std::vector<bool> leftGreen(pos,
false);
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;
504 const bool buildLeftGreenPhase = (haveForbiddenLeftMover && !
myHaveSinglePhase && leftTurnTime > 0 && foundLeftTurnLane
505 && groupOpposites && !groupTram && !groupOther);
508 for (
int i1 = 0; i1 < pos; ++i1) {
509 if (state[i1] ==
'g' && !rightTurnConflicts[i1] && !mergeConflicts[i1]
511 && (!isTurnaround[i1] || (i1 > 0 && leftGreen[i1 - 1]))) {
512 leftGreen[i1] =
true;
513 if (fromEdges[i1]->getSpeed() > minorLeftSpeedThreshold) {
514 if (buildLeftGreenPhase) {
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);
527 std::cout <<
getID() <<
" state=" << state <<
" buildLeft=" << buildLeftGreenPhase <<
" hFLM=" << haveForbiddenLeftMover <<
" turnLane=" << foundLeftTurnLane
528 <<
" \nrtC=" <<
toString(rightTurnConflicts)
529 <<
" \nmC=" <<
toString(mergeConflicts)
530 <<
" \nhTL=" <<
toString(hasTurnLane)
535 straightStates.push_back(state);
537 const std::string vehicleState = state;
538 greenPhases.push_back((
int)logic->
getPhases().size());
541 const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
543 if (chosen.first->getPermissions() ==
SVC_TRAM && (chosen.second ==
nullptr || chosen.second->getPermissions() ==
SVC_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());
551 tramExclusive =
false;
562 state =
addPedestrianPhases(logic, greenTime, minDur, maxDur, earliestEnd, latestEnd, state, crossings, fromEdges, toEdges);
564 for (
int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
567 if (brakingTime > 0) {
570 for (
int i1 = 0; i1 < pos; ++i1) {
571 if (state[i1] !=
'G' && state[i1] !=
'g') {
574 if ((vehicleState[i1] >=
'a' && vehicleState[i1] <=
'z')
575 && buildLeftGreenPhase
576 && !rightTurnConflicts[i1]
577 && !mergeConflicts[i1]
582 maxCross =
MAX2(maxCross, crossingTime[i1]);
585 logic->
addStep(brakingTime, state);
587 if (!buildLeftGreenPhase) {
596 if (buildLeftGreenPhase) {
598 for (
int i1 = 0; i1 < pos; ++i1) {
599 if (state[i1] ==
'Y' || state[i1] ==
'y') {
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;
614 state =
correctMixed(state, fromEdges, fromLanes, buildMixedGreenPhase, mixedGreen);
616 if (state != oldState) {
617 for (
int i1 = 0; i1 < pos; ++i1) {
618 if (mixedGreen[i1]) {
620 int yellowIndex = (int)logic->
getPhases().size() - 1;
621 if (allRedTime > 0) {
624 if (brakingTime > 0) {
629 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
633 logic->
addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
636 if (brakingTime > 0) {
638 for (
int i1 = 0; i1 < pos; ++i1) {
639 if (state[i1] !=
'G' && state[i1] !=
'g') {
643 maxCross =
MAX2(maxCross, crossingTime[i1]);
646 logic->
addStep(brakingTime, state);
651 if (buildMixedGreenPhase) {
657 for (
int i1 = 0; i1 < pos; ++i1) {
658 if (state[i1] ==
'Y' || state[i1] ==
'y') {
662 if (mixedGreen[i1]) {
666 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
667 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
670 logic->
addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
673 if (brakingTime > 0) {
675 for (
int i1 = 0; i1 < pos; ++i1) {
676 if (state[i1] !=
'G' && state[i1] !=
'g') {
680 maxCross =
MAX2(maxCross, crossingTime[i1]);
683 logic->
addStep(brakingTime, state);
690 std::string& s = straightStates.back();
691 std::string leftState = s;
692 for (
int ii = 0; ii < pos; ++ii) {
694 NBEdge* fromEdge = fromEdges[ii];
695 NBEdge* toEdge = toEdges[ii];
705 leftStates.push_back(leftState);
709 if (crossings.size() > 0) {
713 if (logic->
getPhases().size() == 2 && brakingTime > 0
716 logic->
addStep(redTime, std::string(totalNumLinks,
'r'));
719 if (crossings.size() > 0 && !onlyConts) {
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());
745 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
747 minGreenDuration =
MIN2(minGreenDuration, dur);
749 const int patchSeconds = (int)(
STEPS2TIME(cycleTime - totalDuration) / (double)greenPhases.size());
750 const int patchSecondsRest = (int)(
STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (
int)greenPhases.size();
754 || greenPhases.size() == 0) {
760 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
763 if (greenPhases.size() > 0) {
773 if (totalDuration > 0) {
774 if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime) && !isNEMA) {
789 for (
auto c : crossings) {
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) {
808 std::string state,
const std::vector<NBNode::Crossing*>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
813 const std::string orig = state;
817 logic->
addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
819 const SUMOTime pedTime = greenTime - pedClearingTime;
820 if (pedTime >= minPedTime) {
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);
829 logic->
addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
838 std::string result = state;
839 const int pos = (int)(state.size() - crossings.size());
840 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
841 const int i1 = pos + ic;
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) {
850 if (state[i2] !=
'r' && state[i2] !=
's' && (edge == fromEdges[i2] ||
866 for (
int i1 = 0; i1 < pos; ++i1) {
867 if (result[i1] ==
'G') {
868 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
870 if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.
node) {
871 const int i2 = pos + ic;
925 (*i)->removeTrafficLight(&dummy);
936 for (EdgeVector::iterator it = result.begin(); it != result.end();) {
937 if ((*it)->getConnections().size() == 0 || (*it)->isInsideTLS()) {
938 it = result.erase(it);
949 const std::vector<int>& fromLanes,
const std::vector<int>& toLanes) {
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]) {
971 if (greenEdge !=
nullptr) {
972 for (
int i1 = 0; i1 < size; ++i1) {
973 if (fromEdges[i1] == greenEdge) {
988 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
989 if (state[i1] ==
'G') {
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;
1002 if (followsChosen) {
1014 const std::vector<int>& fromLanes,
const std::vector<int>& toLanes) {
1020 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1021 if (state[i1] ==
'G') {
1024 if (
forbidden(state, i1, fromEdges, toEdges)) {
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;
1035 if (preceedsChosen) {
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') {
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))) {
1071 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1072 SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
1073 if ((linkPerm & ~perm) == 0) {
1083 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1084 if (state[i2] ==
'G' &&
foes(fromEdges[i2], toEdges[i2], fromEdges[index], toEdges[index])) {
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) {
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;
1110 if (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true, controlledWithin) || rightTurnConflicts[i1]) {
1113 if (!isTurnaround[i1] && !hadGreenMajor[i1] && !rightTurnConflicts[i1]) {
1114 haveForbiddenLeftMover =
true;
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;
1127 if (state[i1] ==
'r') {
1129 fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) ==
LinkDirection::RIGHT) {
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]);
1143 if (state[i1] ==
's') {
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))) {
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];
1171 mixedGreen[i1] =
true;
1172 if (fromEdges[i1]->getNumLanesThatAllow(
SVC_PASSENGER) > 1) {
1173 buildMixedGreenPhase =
true;
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++) {
1194 foundGreen[j] =
true;
1198 for (
int j = 0; j < (int)foundGreen.size(); j++) {
1199 if (!foundGreen[j]) {
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') {
1207 needYellowPhase =
true;
1211 if (needYellowPhase && brakingTime > 0) {
1212 logic->
addStep(brakingTime, state);
1227 if (allRedTime > 0) {
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';
1242 int minCustomIndex = -1;
1243 int maxCustomIndex = -1;
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);
1267 const int p = (int)logic->
getPhases().size();
1268 for (
int i1 = 0; i1 < n; ++i1) {
1270 for (
int i2 = 0; i2 < p; ++i2) {
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;
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) {
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) {
1323 const int n = (int)state.size();
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);
1345 if (logic !=
nullptr) {
1363 int greenPhases = 0;
1364 for (
const auto& phase : tllDummy->
getPhases()) {
1365 if (phase.state.find_first_of(
"gG") != std::string::npos) {
1371 controlledNode->removeTrafficLight(&dummy);
1373 return greenPhases <= 2;
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) {
1395 const int totalNumLinks = (int)straightStates[0].size();
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);
1409 logic->
addStep(dur, left1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft));
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);
1418 logic->
addStep(dur, left2, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft + 4));
1423 std::string straight1 =
filterState(straightStates[i], fromEdges, e1);
1424 if (straight1 ==
"") {
1428 logic->
addStep(dur, straight1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft + 5));
1431 std::map<int, int> names;
1432 for (
int i = 0; i < (int)logic->
getPhases().size(); i++) {
1440 if (ring1[2] == 0 && ring1[3] == 0) {
1443 fixDurationSum(logic, names, ring1[0], ring1[1], ring2[0], ring2[1]);
1444 fixDurationSum(logic, names, ring1[2], ring1[3], ring2[2], ring2[3]);
1456 bool haveGreen =
false;
1457 for (
int j = 0; j < (int)state.size(); j++) {
1458 if (fromEdges[j] != e) {
1460 }
else if (state[j] !=
'r') {
1473 for (
int i = 0; i < (int)vec.size(); i++) {
1474 if (names.count(vec[i]) == 0) {
1476 if (names.count(vec[i] - 1) > 0) {
1477 vec[i] = vec[i] - 1;
1490 std::set<int> ring1existing;
1491 std::set<int> ring2existing;
1492 if (names.count(ring1a) != 0) {
1493 ring1existing.insert(ring1a);
1495 if (names.count(ring1b) != 0) {
1496 ring1existing.insert(ring1b);
1498 if (names.count(ring2a) != 0) {
1499 ring2existing.insert(ring2a);
1501 if (names.count(ring2b) != 0) {
1502 ring2existing.insert(ring2b);
1504 if (ring1existing.size() > 0 && ring2existing.size() > 0 &&
1505 ring1existing.size() != ring2existing.size()) {
1507 if (ring1existing.size() < ring2existing.size()) {
1508 pI = names.find(*ring1existing.begin())->second;
1510 pI = names.find(*ring2existing.begin())->second;
1513 SUMOTime newMaxDur = 2 * p.maxDur + p.yellow + p.red;
#define WRITE_WARNINGF(...)
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
std::string time2string(SUMOTime t)
convert SUMOTime to string
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
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.
@ TRAFFIC_LIGHT_RIGHT_ON_RED
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
const std::vector< Connection > & getConnections() const
Returns the connections.
NBNode * getToNode() const
Returns the destination node of the edge.
const std::string & getID() const
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
std::vector< Connection > getConnectionsFromLane(int lane, NBEdge *to=nullptr, int toLane=-1) const
Returns connections from a given lane.
int getNumLanes() const
Returns the number of lanes.
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
NBNode * getFromNode() const
Returns the origin node of the edge.
NBEdge * getTurnDestination(bool possibleDestination=false) const
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
A definition of a pedestrian crossing.
const NBNode * node
The parent node of this crossing.
EdgeVector edges
The edges being crossed.
Represents a single node (junction) during network building.
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
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...
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.
Sorts edges by their priority within the node they end at.
A traffic light logics which must be computed (only nodes/edges are given)
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
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.
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.
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
void collectLinks()
Collects the links participating in this traffic light.
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
static bool hasCrossing(const NBEdge *from, const NBEdge *to, const std::vector< NBNode::Crossing * > &crossings)
compute whether the given connection is crossed by pedestrians
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.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
int getToPrio(const NBEdge *const e)
Returns this edge's priority at the node it ends at.
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
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.
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)
void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic *logic, const std::string &state)
double getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
std::string allowSingleEdge(std::string state, const EdgeVector &fromEdges)
bool hasStraightConnection(const NBEdge *fromEdge)
check whether there is a straight connection from this edge
std::pair< NBEdge *, NBEdge * > getBestCombination(const EdgeVector &edges)
Returns the combination of two edges from the given which has most unblocked streams.
void initNeedsContRelation() const
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.
static EdgeVector getConnectedOuterEdges(const EdgeVector &incoming)
get edges that have connections
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
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
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.
static const double MIN_SPEED_CROSSING_TIME
minimum speed for computing time to cross intersection
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..)
bool myNeedsContRelationReady
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.
bool myRightOnRedConflictsReady
NeedsContRelation myNeedsContRelation
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
const std::string & getID() const
Returns the id.
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.
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.
data structure for caching needsCont information