42#define MIN_GREEN_TIME 5
48#define DEBUGCOND (true)
49#define DEBUGEDGE(edge) (true)
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;
131 if (prio1 == prio2) {
160#ifdef DEBUG_STREAM_ORDERING
162 std::cout <<
" sign=" << sign <<
" w1=" << w1 <<
" w2=" << w2 <<
" val=" << val
163 <<
" c1=" << (*e1c).getDescription(e1)
164 <<
" c2=" << (*e2c).getDescription(e2)
172#ifdef DEBUG_STREAM_ORDERING
174 std::cout <<
" computeUnblockedWeightedStreamNumber e1=" << e1->
getID() <<
" e2=" << e2->
getID() <<
" val=" << val <<
"\n";
181std::pair<NBEdge*, NBEdge*>
183 std::pair<NBEdge*, NBEdge*> bestPair(
static_cast<NBEdge*
>(
nullptr),
static_cast<NBEdge*
>(
nullptr));
184 double bestValue = -std::numeric_limits<double>::max();
185 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
186 for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
188 if (value > bestValue) {
190 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
191 }
else if (value == bestValue) {
193 const double oa =
GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
194 if (fabs(oa - ca) < NUMERICAL_EPS) {
195 if (bestPair.first->getID() < (*i)->getID()) {
196 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
198 }
else if (oa < ca) {
199 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
204 if (bestValue <= 0) {
206 if (bestPair.first->getPriority() < bestPair.second->getPriority()) {
207 std::swap(bestPair.first, bestPair.second);
209 bestPair.second =
nullptr;
211#ifdef DEBUG_STREAM_ORDERING
220std::pair<NBEdge*, NBEdge*>
222 if (incoming.size() == 1) {
224 std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(),
static_cast<NBEdge*
>(
nullptr));
232 used.push_back(*incoming.begin());
235 for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio ==
getToPrio(*i); ++i) {
239 if (used.size() < 2) {
243#ifdef DEBUG_STREAM_ORDERING
249 incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
250 if (ret.second !=
nullptr) {
251 incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
286 std::vector<std::pair<NBEdge*, NBEdge*> > chosenList;
287 std::vector<std::string> straightStates;
288 std::vector<std::string> leftStates;
293 std::vector<bool> isTurnaround;
294 std::vector<bool> hasTurnLane;
295 std::vector<int> fromLanes;
296 std::vector<int> toLanes;
297 std::vector<SUMOTime> crossingTime;
298 int totalNumLinks = 0;
299 for (
NBEdge*
const fromEdge : incoming) {
300 const int numLanes = fromEdge->getNumLanes();
302 for (
int i2 = 0; i2 < numLanes; i2++) {
303 bool hasLeft =
false;
304 bool hasPartLeft =
false;
305 bool hasStraight =
false;
306 bool hasRight =
false;
307 bool hasTurnaround =
false;
309 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
312 fromEdges.push_back(fromEdge);
313 fromLanes.push_back(i2);
314 toLanes.push_back(approached.toLane);
315 toEdges.push_back(approached.toEdge);
316 if (approached.vmax < NUMERICAL_EPS || (fromEdge->getPermissions() &
SVC_PASSENGER) == 0
317 || (approached.toEdge->getPermissions() &
SVC_PASSENGER) == 0) {
318 crossingTime.push_back(0);
323 if (approached.toEdge !=
nullptr) {
324 isTurnaround.push_back(fromEdge->isTurningDirectionAt(approached.toEdge));
326 isTurnaround.push_back(
true);
328 LinkDirection dir = fromEdge->getToNode()->getDirection(fromEdge, approached.toEdge);
338 hasTurnaround =
true;
343 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
346 hasTurnLane.push_back(
347 (hasLeft && !hasPartLeft && !hasStraight && !hasRight)
348 || (hasPartLeft && !hasLeft && !hasStraight && !hasRight)
349 || (hasPartLeft && hasLeft && edgeHasStraight && !hasRight)
350 || (!hasLeft && !hasPartLeft && !hasTurnaround && hasRight));
356 std::vector<NBNode::Crossing*> crossings;
358 const std::vector<NBNode::Crossing*>& c = node->getCrossings();
361 node->setCrossingTLIndices(
getID(), totalNumLinks);
363 copy(c.begin(), c.end(), std::back_inserter(crossings));
364 totalNumLinks += (int)c.size();
381 std::vector<int> greenPhases;
382 std::vector<bool> hadGreenMajor(totalNumLinks,
false);
383 while (toProc.size() > 0) {
384 bool groupTram =
false;
385 bool groupOther =
false;
386 std::pair<NBEdge*, NBEdge*> chosen;
387 std::set<const NBEdge*> chosenSet;
388 if (groupOpposites) {
389 if (incoming.size() == 2) {
392 double angle = fabs(
NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
395 chosen = std::pair<NBEdge*, NBEdge*>(toProc[0],
static_cast<NBEdge*
>(
nullptr));
396 toProc.erase(toProc.begin());
402 if (chosen.second ==
nullptr && chosen.first->getPermissions() ==
SVC_TRAM) {
404 for (
auto it = toProc.begin(); it != toProc.end();) {
405 if ((*it)->getPermissions() ==
SVC_TRAM) {
406 it = toProc.erase(it);
414 NBEdge* chosenEdge = toProc[0];
415 chosen = std::pair<NBEdge*, NBEdge*>(chosenEdge,
static_cast<NBEdge*
>(
nullptr));
416 toProc.erase(toProc.begin());
424 if (groupTram || groupOther) {
425 for (
auto it = toProc.begin(); it != toProc.end();) {
426 if ((*it)->getPermissions() == perms) {
427 it = toProc.erase(it);
435 std::string state(totalNumLinks,
'r');
441 chosenList.push_back(chosen);
442 chosenSet.insert(chosen.first);
443 if (chosen.second !=
nullptr) {
444 chosenSet.insert(chosen.second);
447 for (
const NBEdge* e : chosenSet) {
449 std::vector<NBEdge*> parallelBikeEdges;
450 for (
NBEdge* cand : toProc) {
452 double angle = fabs(
NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), cand->getAngleAtNode(cand->getToNode())));
455 parallelBikeEdges.push_back(cand);
459 for (
NBEdge* be : parallelBikeEdges) {
462 std::cout <<
" chosen=" << e->getID() <<
" be=" << be->getID() <<
"\n";
465 chosenSet.insert(be);
466 toProc.erase(std::find(toProc.begin(), toProc.end(), be));
472 bool haveGreen =
false;
473 for (
const NBEdge*
const fromEdge : incoming) {
474 const bool inChosen = chosenSet.count(fromEdge) != 0;
475 const int numLanes = fromEdge->getNumLanes();
476 for (
int i2 = 0; i2 < numLanes; i2++) {
478 if (!fromEdge->mayBeTLSControlled(i2, approached.toEdge, approached.toLane)) {
484 maxSpeed =
MAX2(maxSpeed, fromEdge->getSpeed());
498 std::cout <<
" state after plain straight movers " << state <<
"\n";
503 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
506 }
else if (groupOther) {
511 std::cout <<
" state after grouping by vClass " << state <<
"\n";
515 state =
allowUnrelated(state, fromEdges, toEdges, isTurnaround, crossings);
519 std::cout <<
" state after finding allowUnrelated " << state <<
"\n";
524 bool haveForbiddenLeftMover =
false;
525 std::vector<bool> rightTurnConflicts(pos,
false);
526 std::vector<bool> mergeConflicts(pos,
false);
527 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
528 for (
int i1 = 0; i1 < pos; ++i1) {
529 if (state[i1] ==
'G') {
530 hadGreenMajor[i1] =
true;
535 std::cout <<
" state after correcting left movers=" << state <<
"\n";
539 std::vector<bool> leftGreen(pos,
false);
541 bool foundLeftTurnLane =
false;
542 for (
int i1 = 0; i1 < pos; ++i1) {
543 if (state[i1] ==
'g' && !rightTurnConflicts[i1] && !mergeConflicts[i1] && hasTurnLane[i1]) {
544 foundLeftTurnLane =
true;
547 const bool buildLeftGreenPhase = (haveForbiddenLeftMover && !
myHaveSinglePhase && leftTurnTime > 0 && foundLeftTurnLane
548 && groupOpposites && !groupTram && !groupOther);
551 for (
int i1 = 0; i1 < pos; ++i1) {
552 if (state[i1] ==
'g' && !rightTurnConflicts[i1] && !mergeConflicts[i1]
554 && (!isTurnaround[i1] || (i1 > 0 && leftGreen[i1 - 1]))) {
555 leftGreen[i1] =
true;
556 if (fromEdges[i1]->getSpeed() > minorLeftSpeedThreshold) {
557 if (buildLeftGreenPhase) {
560 }
else if (!isTurnaround[i1]) {
561 WRITE_WARNINGF(
TL(
"Minor green from edge '%' to edge '%' exceeds %m/s. Maybe a left-turn lane is missing."),
562 fromEdges[i1]->
getID(), toEdges[i1]->
getID(), minorLeftSpeedThreshold);
570 std::cout <<
getID() <<
" state=" << state <<
" buildLeft=" << buildLeftGreenPhase <<
" hFLM=" << haveForbiddenLeftMover <<
" turnLane=" << foundLeftTurnLane
571 <<
" \nrtC=" <<
toString(rightTurnConflicts)
572 <<
" \nmC=" <<
toString(mergeConflicts)
573 <<
" \nhTL=" <<
toString(hasTurnLane)
578 straightStates.push_back(state);
580 const std::string vehicleState = state;
581 greenPhases.push_back((
int)logic->
getPhases().size());
584 const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
586 if (chosen.first->getPermissions() ==
SVC_TRAM && (chosen.second ==
nullptr || chosen.second->getPermissions() ==
SVC_TRAM)) {
589 bool tramExclusive =
true;
590 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
591 if (state[i1] ==
'G') {
592 SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
594 tramExclusive =
false;
605 state =
addPedestrianPhases(logic, greenTime, minDur, maxDur, earliestEnd, latestEnd, state, crossings, fromEdges, toEdges);
607 for (
int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
610 if (brakingTime > 0) {
613 for (
int i1 = 0; i1 < pos; ++i1) {
614 if (state[i1] !=
'G' && state[i1] !=
'g') {
617 if ((vehicleState[i1] >=
'a' && vehicleState[i1] <=
'z')
618 && buildLeftGreenPhase
619 && !rightTurnConflicts[i1]
620 && !mergeConflicts[i1]
625 maxCross =
MAX2(maxCross, crossingTime[i1]);
628 logic->
addStep(brakingTime, state);
630 if (!buildLeftGreenPhase) {
639 if (buildLeftGreenPhase) {
641 for (
int i1 = 0; i1 < pos; ++i1) {
642 if (state[i1] ==
'Y' || state[i1] ==
'y') {
650 leftStates.push_back(state);
651 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
652 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
653 bool buildMixedGreenPhase =
false;
654 std::vector<bool> mixedGreen(pos,
false);
655 const std::string oldState = state;
657 state =
correctMixed(state, fromEdges, fromLanes, buildMixedGreenPhase, mixedGreen);
659 if (state != oldState) {
660 for (
int i1 = 0; i1 < pos; ++i1) {
661 if (mixedGreen[i1]) {
663 int yellowIndex = (int)logic->
getPhases().size() - 1;
664 if (allRedTime > 0) {
667 if (brakingTime > 0) {
672 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
676 logic->
addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
679 if (brakingTime > 0) {
681 for (
int i1 = 0; i1 < pos; ++i1) {
682 if (state[i1] !=
'G' && state[i1] !=
'g') {
686 maxCross =
MAX2(maxCross, crossingTime[i1]);
689 logic->
addStep(brakingTime, state);
694 if (buildMixedGreenPhase) {
700 for (
int i1 = 0; i1 < pos; ++i1) {
701 if (state[i1] ==
'Y' || state[i1] ==
'y') {
705 if (mixedGreen[i1]) {
709 state =
allowCompatible(state, fromEdges, toEdges, fromLanes, toLanes);
710 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, toLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts, mergeConflicts);
713 logic->
addStep(leftTurnTime, state, minDur, maxDur, earliestEnd, latestEnd);
716 if (brakingTime > 0) {
718 for (
int i1 = 0; i1 < pos; ++i1) {
719 if (state[i1] !=
'G' && state[i1] !=
'g') {
723 maxCross =
MAX2(maxCross, crossingTime[i1]);
726 logic->
addStep(brakingTime, state);
733 std::string& s = straightStates.back();
734 std::string leftState = s;
735 for (
int ii = 0; ii < pos; ++ii) {
737 NBEdge* fromEdge = fromEdges[ii];
738 NBEdge* toEdge = toEdges[ii];
748 leftStates.push_back(leftState);
752 if (crossings.size() > 0) {
756 if (logic->
getPhases().size() == 2 && brakingTime > 0
759 logic->
addStep(redTime, std::string(totalNumLinks,
'r'));
762 if (crossings.size() > 0 && !onlyConts) {
772 if (nemaLogic ==
nullptr) {
773 WRITE_WARNINGF(
TL(
"Generating NEMA phases is not support for traffic light '%' with % incoming edges. Using tlType 'actuated' as fallback"),
getID(), incoming.size());
788 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
790 minGreenDuration =
MIN2(minGreenDuration, dur);
792 const int patchSeconds = (int)(
STEPS2TIME(cycleTime - totalDuration) / (double)greenPhases.size());
793 const int patchSecondsRest = (int)(
STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (
int)greenPhases.size();
797 || greenPhases.size() == 0) {
803 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
806 if (greenPhases.size() > 0) {
816 if (totalDuration > 0) {
817 if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime) && !isNEMA) {
832 for (
auto c : crossings) {
836 for (EdgeVector::const_iterator it_e = cross.
edges.begin(); it_e != cross.
edges.end(); ++it_e) {
837 const NBEdge* edge = *it_e;
838 if (edge == from || edge == to) {
851 std::string state,
const std::vector<NBNode::Crossing*>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
856 const std::string orig = state;
860 logic->
addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
862 const SUMOTime pedTime = greenTime - pedClearingTime;
863 if (pedTime >= minPedTime) {
865 const int pedStates = (int)crossings.size();
866 logic->
addStep(pedTime, state, minDur, maxDur, earliestEnd, latestEnd);
867 state = state.substr(0, state.size() - pedStates) + std::string(pedStates,
'r');
868 logic->
addStep(pedClearingTime, state);
872 logic->
addStep(greenTime, state, minDur, maxDur, earliestEnd, latestEnd);
881 std::string result = state;
882 const int pos = (int)(state.size() - crossings.size());
883 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
884 const int i1 = pos + ic;
889 if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.
node) {
890 for (EdgeVector::const_iterator it = cross.
edges.begin(); it != cross.
edges.end(); ++it) {
893 if (state[i2] !=
'r' && state[i2] !=
's' && (edge == fromEdges[i2] ||
909 for (
int i1 = 0; i1 < pos; ++i1) {
910 if (result[i1] ==
'G') {
911 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
913 if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.
node) {
914 const int i2 = pos + ic;
968 (*i)->removeTrafficLight(&dummy);
979 for (EdgeVector::iterator it = result.begin(); it != result.end();) {
980 if ((*it)->getConnections().size() == 0 || (*it)->isInsideTLS()) {
981 it = result.erase(it);
992 const std::vector<int>& fromLanes,
const std::vector<int>& toLanes) {
1003 const int size = (int)fromEdges.size();
1004 NBEdge* greenEdge =
nullptr;
1005 for (
int i1 = 0; i1 < size; ++i1) {
1006 if (state[i1] ==
'G') {
1007 if (greenEdge ==
nullptr) {
1008 greenEdge = fromEdges[i1];
1009 }
else if (greenEdge != fromEdges[i1]) {
1014 if (greenEdge !=
nullptr) {
1015 for (
int i1 = 0; i1 < size; ++i1) {
1016 if (fromEdges[i1] == greenEdge) {
1031 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1032 if (state[i1] ==
'G') {
1038 bool followsChosen =
false;
1039 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1040 if (state[i2] ==
'G' && fromEdges[i1] == toEdges[i2]) {
1041 followsChosen =
true;
1045 if (followsChosen) {
1057 const std::vector<int>& fromLanes,
const std::vector<int>& toLanes) {
1063 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1064 if (state[i1] ==
'G') {
1067 if (
forbidden(state, i1, fromEdges, toEdges)) {
1070 bool preceedsChosen =
false;
1071 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1072 if (state[i2] ==
'G' && fromEdges[i2] == toEdges[i1]
1073 && fromLanes[i2] == toLanes[i1]) {
1074 preceedsChosen =
true;
1078 if (preceedsChosen) {
1090 const std::vector<bool>& isTurnaround,
1091 const std::vector<NBNode::Crossing*>& crossings) {
1092 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1093 if (state[i1] ==
'G') {
1097 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1098 if (state[i2] ==
'G' && !isTurnaround[i2] &&
1099 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
1114 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1115 SVCPermissions linkPerm = (fromEdges[i1]->getPermissions() & toEdges[i1]->getPermissions());
1116 if ((linkPerm & ~perm) == 0) {
1126 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1127 if (state[i2] ==
'G' &&
foes(fromEdges[i2], toEdges[i2], fromEdges[index], toEdges[index])) {
1137 const std::vector<bool>& isTurnaround,
1138 const std::vector<int>& fromLanes,
1139 const std::vector<int>& toLanes,
1140 const std::vector<bool>& hadGreenMajor,
1141 bool& haveForbiddenLeftMover,
1142 std::vector<bool>& rightTurnConflicts,
1143 std::vector<bool>& mergeConflicts) {
1145 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1146 if (state[i1] ==
'G') {
1147 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1148 if ((state[i2] ==
'G' || state[i2] ==
'g')) {
1150 fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
1151 rightTurnConflicts[i1] =
true;
1153 if (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true, controlledWithin) || rightTurnConflicts[i1]) {
1156 if (!isTurnaround[i1] && !hadGreenMajor[i1] && !rightTurnConflicts[i1]) {
1157 haveForbiddenLeftMover =
true;
1159 }
else if (fromEdges[i1] == fromEdges[i2]
1160 && fromLanes[i1] != fromLanes[i2]
1161 && toEdges[i1] == toEdges[i2]
1162 && toLanes[i1] == toLanes[i2]
1163 && fromEdges[i1]->getToNode()->mergeConflictYields(fromEdges[i1], fromLanes[i1], fromLanes[i2], toEdges[i1], toLanes[i1])) {
1164 mergeConflicts[i1] =
true;
1170 if (state[i1] ==
'r') {
1172 fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) ==
LinkDirection::RIGHT) {
1175 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1176 if (state[i2] ==
'G' && !isTurnaround[i2] &&
1177 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
1178 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
1179 const LinkDirection foeDir = fromEdges[i2]->getToNode()->getDirection(fromEdges[i2], toEdges[i2]);
1186 if (state[i1] ==
's') {
1188 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1189 if (state[i2] ==
'G' && !isTurnaround[i2] &&
1190 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
1191 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
1205 const std::vector<int>& fromLanes,
1206 bool& buildMixedGreenPhase, std::vector<bool>& mixedGreen) {
1207 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
1208 if ((state[i1] ==
'G' || state[i1] ==
'g')) {
1209 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
1210 if (i1 != i2 && fromEdges[i1] == fromEdges[i2] && fromLanes[i1] == fromLanes[i2]
1211 && state[i2] !=
'G' && state[i2] !=
'g') {
1212 state[i1] = state[i2];
1214 mixedGreen[i1] =
true;
1215 if (fromEdges[i1]->getNumLanesThatAllow(
SVC_PASSENGER) > 1) {
1216 buildMixedGreenPhase =
true;
1228 const std::vector<NBNode::Crossing*>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
1229 const int vehLinks = totalNumLinks - (int)crossings.size();
1230 std::vector<bool> foundGreen(crossings.size(),
false);
1231 const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->
getPhases();
1232 for (
int i = 0; i < (int)phases.size(); i++) {
1233 const std::string state = phases[i].state;
1234 for (
int j = 0; j < (int)crossings.size(); j++) {
1237 foundGreen[j] =
true;
1241 for (
int j = 0; j < (int)foundGreen.size(); j++) {
1242 if (!foundGreen[j]) {
1244 if (phases.size() > 0) {
1245 bool needYellowPhase =
false;
1246 std::string state = phases.back().state;
1247 for (
int i1 = 0; i1 < vehLinks; ++i1) {
1248 if (state[i1] ==
'G' || state[i1] ==
'g') {
1250 needYellowPhase =
true;
1254 if (needYellowPhase && brakingTime > 0) {
1255 logic->
addStep(brakingTime, state);
1270 if (allRedTime > 0) {
1272 std::string allRedState = state;
1273 for (
int i = 0; i < (int)state.size(); i++) {
1274 if (allRedState[i] ==
'Y' || allRedState[i] ==
'y') {
1275 allRedState[i] =
'r';
1285 int minCustomIndex = -1;
1286 int maxCustomIndex = -1;
1289 const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
1290 for (
auto crossing : c) {
1291 minCustomIndex =
MIN2(minCustomIndex, crossing->customTLIndex);
1292 minCustomIndex =
MIN2(minCustomIndex, crossing->customTLIndex2);
1293 maxCustomIndex =
MAX2(maxCustomIndex, crossing->customTLIndex);
1294 maxCustomIndex =
MAX2(maxCustomIndex, crossing->customTLIndex2);
1310 const int p = (int)logic->
getPhases().size();
1311 for (
int i1 = 0; i1 < n; ++i1) {
1313 for (
int i2 = 0; i2 < p; ++i2) {
1330 std::vector<bool> alwaysGreen(n,
true);
1331 for (
int i1 = 0; i1 < n; ++i1) {
1332 for (
const auto& phase : logic->
getPhases()) {
1333 if (phase.state[i1] !=
'G') {
1334 alwaysGreen[i1] =
false;
1339 const int p = (int)logic->
getPhases().size();
1340 for (
int i1 = 0; i1 < n; ++i1) {
1341 if (alwaysGreen[i1]) {
1342 for (
int i2 = 0; i2 < p; ++i2) {
1353 const int p = (int)logic->
getPhases().size();
1354 for (
int i1 = 0; i1 < n; ++i1) {
1355 if (fromEdges[i1]->isInsideTLS()) {
1356 for (
int i2 = 0; i2 < p; ++i2) {
1366 const int n = (int)state.size();
1368 for (
int i1 = 0; i1 < n; ++i1) {
1369 if (state[i1] ==
'y' && !fromEdges[i1]->isInsideTLS()) {
1370 for (
int i2 = 0; i2 < n; ++i2) {
1371 if (fromEdges[i2]->isInsideTLS()) {
1372 double gapSpeed = (toEdges[i1]->getSpeed() + fromEdges[i2]->getSpeed()) / 2;
1373 double time = fromEdges[i1]->getGeometry().back().distanceTo2D(fromEdges[i2]->getGeometry().back()) / gapSpeed;
1374 maxTime =
MAX2(maxTime, time);
1388 if (logic !=
nullptr) {
1406 int greenPhases = 0;
1407 for (
const auto& phase : tllDummy->
getPhases()) {
1408 if (phase.state.find_first_of(
"gG") != std::string::npos) {
1414 controlledNode->removeTrafficLight(&dummy);
1416 return greenPhases <= 2;
1423 const std::vector<std::pair<NBEdge*, NBEdge*> >& chosenList,
1424 const std::vector<std::string>& straightStates,
1425 const std::vector<std::string>& leftStates) {
1426 if (chosenList.size() != 2) {
1438 const int totalNumLinks = (int)straightStates[0].size();
1440 std::vector<int> ring1({1, 2, 3, 4});
1441 std::vector<int> ring2({5, 6, 7, 8});
1442 std::vector<int> barrier1({4, 8});
1443 std::vector<int> barrier2({2, 6});
1444 int phaseNameLeft = 1;
1445 for (
int i = 0; i < (int)chosenList.size(); i++) {
1446 NBEdge* e1 = chosenList[i].first;
1447 assert(e1 !=
nullptr);
1448 NBEdge* e2 = chosenList[i].second;
1449 if (i < (
int)leftStates.size()) {
1450 std::string left1 =
filterState(leftStates[i], fromEdges, e1);
1452 logic->
addStep(dur, left1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft));
1455 if (e2 !=
nullptr) {
1456 std::string straight2 =
filterState(straightStates[i], fromEdges, e2);
1457 logic->
addStep(dur, straight2, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft + 1));
1458 if (i < (
int)leftStates.size()) {
1459 std::string left2 =
filterState(leftStates[i], fromEdges, e2);
1461 logic->
addStep(dur, left2, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft + 4));
1466 std::string straight1 =
filterState(straightStates[i], fromEdges, e1);
1467 if (straight1 ==
"") {
1471 logic->
addStep(dur, straight1, minMinDur, maxDur, earliestEnd, latestEnd, vehExt, yellow, red,
toString(phaseNameLeft + 5));
1474 std::map<int, int> names;
1475 for (
int i = 0; i < (int)logic->
getPhases().size(); i++) {
1483 if (ring1[2] == 0 && ring1[3] == 0) {
1486 fixDurationSum(logic, names, ring1[0], ring1[1], ring2[0], ring2[1]);
1487 fixDurationSum(logic, names, ring1[2], ring1[3], ring2[2], ring2[3]);
1499 bool haveGreen =
false;
1500 for (
int j = 0; j < (int)state.size(); j++) {
1501 if (fromEdges[j] != e) {
1503 }
else if (state[j] !=
'r') {
1516 for (
int i = 0; i < (int)vec.size(); i++) {
1517 if (names.count(vec[i]) == 0) {
1519 if (names.count(vec[i] - 1) > 0) {
1520 vec[i] = vec[i] - 1;
1533 std::set<int> ring1existing;
1534 std::set<int> ring2existing;
1535 if (names.count(ring1a) != 0) {
1536 ring1existing.insert(ring1a);
1538 if (names.count(ring1b) != 0) {
1539 ring1existing.insert(ring1b);
1541 if (names.count(ring2a) != 0) {
1542 ring2existing.insert(ring2a);
1544 if (names.count(ring2b) != 0) {
1545 ring2existing.insert(ring2b);
1547 if (ring1existing.size() > 0 && ring2existing.size() > 0 &&
1548 ring1existing.size() != ring2existing.size()) {
1550 if (ring1existing.size() < ring2existing.size()) {
1551 pI = names.find(*ring1existing.begin())->second;
1553 pI = names.find(*ring2existing.begin())->second;
1556 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 isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
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 occurrences 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.
NBTrafficLightLogic * compute(const OptionsCont &oc)
Computes the traffic light logic.
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.
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,...
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
A structure which describes a connection between edges or lanes.
data structure for caching needsCont information