46 #define MIN_GREEN_TIME 5 49 #define DEBUGCOND true 55 const std::vector<NBNode*>& junctions,
SUMOTime offset,
58 myHaveSinglePhase(false) {
104 for (
int e1l = 0; e1l < e1->
getNumLanes(); e1l++) {
106 for (
int e2l = 0; e2l < e2->
getNumLanes(); e2l++) {
108 for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
112 for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
116 if (!
forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge,
true)) {
128 std::pair<NBEdge*, NBEdge*>
130 std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
131 double bestValue = -1;
132 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
133 for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
135 if (value > bestValue) {
137 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
138 }
else if (value == bestValue) {
140 const double oa =
GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
142 if (bestPair.first->getID() < (*i)->getID()) {
143 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
145 }
else if (oa < ca) {
146 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
155 std::pair<NBEdge*, NBEdge*>
157 if (incoming.size() == 1) {
159 std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(),
static_cast<NBEdge*
>(0));
167 used.push_back(*incoming.begin());
170 for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio ==
getToPrio(*i); ++i) {
174 if (used.size() < 2) {
178 #ifdef DEBUG_STREAM_ORDERING 184 incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
185 incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
206 std::vector<bool> isTurnaround;
207 std::vector<int> fromLanes;
210 for (
int i1 = 0; i1 < (int)incoming.size(); i1++) {
211 int noLanes = incoming[i1]->getNumLanes();
212 noLanesAll += noLanes;
213 for (
int i2 = 0; i2 < noLanes; i2++) {
214 NBEdge* fromEdge = incoming[i1];
216 noLinksAll += (int) approached.size();
217 for (
int i3 = 0; i3 < (int)approached.size(); i3++) {
218 if (!fromEdge->
mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
222 assert(i3 < (
int)approached.size());
223 NBEdge* toEdge = approached[i3].toEdge;
224 fromEdges.push_back(fromEdge);
225 fromLanes.push_back((
int)i2);
226 toEdges.push_back(toEdge);
230 isTurnaround.push_back(
true);
236 std::vector<NBNode::Crossing*> crossings;
238 const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
241 (*i)->setCrossingTLIndices(
getID(), noLinksAll);
243 copy(c.begin(), c.end(), std::back_inserter(crossings));
244 noLinksAll += (int)c.size();
252 std::vector<int> greenPhases;
253 std::vector<bool> hadGreenMajor(noLinksAll,
false);
254 while (toProc.size() > 0) {
255 std::pair<NBEdge*, NBEdge*> chosen;
256 if (incoming.size() == 2) {
259 double angle = fabs(
NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
262 chosen = std::pair<NBEdge*, NBEdge*>(toProc[0],
static_cast<NBEdge*
>(0));
263 toProc.erase(toProc.begin());
271 std::string state((
int) noLinksAll,
'r');
274 for (
int i1 = 0; i1 < (int) incoming.size(); ++i1) {
275 NBEdge* fromEdge = incoming[i1];
276 const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second;
278 for (
int i2 = 0; i2 < numLanes; i2++) {
280 for (
int i3 = 0; i3 < (int)approached.size(); ++i3) {
281 if (!fromEdge->
mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
296 for (
int i1 = 0; i1 < pos; ++i1) {
297 if (state[i1] ==
'G') {
302 if (state[i2] ==
'G' && !isTurnaround[i2] &&
303 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
307 if (!isForbidden && !
hasCrossing(fromEdges[i1], toEdges[i1], crossings)) {
313 bool haveForbiddenLeftMover =
false;
314 std::vector<bool> rightTurnConflicts(pos,
false);
315 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
316 for (
int i1 = 0; i1 < pos; ++i1) {
317 if (state[i1] ==
'G') {
318 hadGreenMajor[i1] =
true;
322 const std::string vehicleState = state;
323 greenPhases.push_back((
int)logic->
getPhases().size());
324 state =
addPedestrianPhases(logic, greenTime, minDur, maxDur, state, crossings, fromEdges, toEdges);
326 for (
int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
329 const bool buildLeftGreenPhase = haveForbiddenLeftMover && !
myHaveSinglePhase && leftTurnTime > 0;
330 if (brakingTime > 0) {
332 for (
int i1 = 0; i1 < pos; ++i1) {
333 if (state[i1] !=
'G' && state[i1] !=
'g') {
336 if ((vehicleState[i1] >=
'a' && vehicleState[i1] <=
'z') && buildLeftGreenPhase && !rightTurnConflicts[i1]) {
342 logic->
addStep(brakingTime, state);
348 if (buildLeftGreenPhase) {
350 for (
int i1 = 0; i1 < pos; ++i1) {
351 if (state[i1] ==
'Y' || state[i1] ==
'y') {
355 if (state[i1] ==
'g') {
360 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
363 logic->
addStep(leftTurnTime, state, minDur, maxDur);
366 if (brakingTime > 0) {
367 for (
int i1 = 0; i1 < pos; ++i1) {
368 if (state[i1] !=
'G' && state[i1] !=
'g') {
374 logic->
addStep(brakingTime, state);
381 if (crossings.size() > 0) {
385 if (logic->
getPhases().size() == 2 && brakingTime > 0
388 logic->
addStep(redTime, std::string(noLinksAll,
'r'));
397 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
399 greenPhaseTime += dur;
400 minGreenDuration =
MIN2(minGreenDuration, dur);
402 const int patchSeconds = (int)(
STEPS2TIME(cycleTime - totalDuration) / greenPhases.size());
403 const int patchSecondsRest = (int)(
STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (
int)greenPhases.size();
407 || greenPhases.size() == 0) {
413 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
416 if (greenPhases.size() > 0) {
426 if (totalDuration > 0) {
427 if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
442 for (
auto c : crossings) {
446 for (EdgeVector::const_iterator it_e = cross.
edges.begin(); it_e != cross.
edges.end(); ++it_e) {
447 const NBEdge* edge = *it_e;
448 if (edge == from || edge == to) {
461 std::string state,
const std::vector<NBNode::Crossing*>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
464 const std::string orig = state;
468 logic->
addStep(greenTime, state, minDur, maxDur);
470 const SUMOTime pedTime = greenTime - pedClearingTime;
471 if (pedTime >= minPedTime) {
473 const int pedStates = (int)crossings.size();
474 logic->
addStep(pedTime, state, minDur, maxDur);
475 state = state.substr(0, state.size() - pedStates) + std::string(pedStates,
'r');
476 logic->
addStep(pedClearingTime, state);
480 logic->
addStep(greenTime, state, minDur, maxDur);
489 std::string result = state;
490 const int pos = (int)(state.size() - crossings.size());
491 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
492 const int i1 = pos + ic;
497 if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.
node) {
498 for (EdgeVector::const_iterator it = cross.
edges.begin(); it != cross.
edges.end(); ++it) {
501 if (state[i2] !=
'r' && state[i2] !=
's' && (edge == fromEdges[i2] ||
517 for (
int i1 = 0; i1 < pos; ++i1) {
518 if (result[i1] ==
'G') {
519 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
521 if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.
node) {
522 const int i2 = pos + ic;
575 (*i)->removeTrafficLight(&dummy);
586 for (EdgeVector::iterator it = result.begin(); it != result.end();) {
587 if ((*it)->getConnections().size() == 0 || (*it)->isInnerEdge()) {
588 it = result.erase(it);
602 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
603 if (state[i1] ==
'G') {
606 bool followsChosen =
false;
607 for (
int i2 = 0; i2 < (int)fromEdges.size() && !followsChosen; ++i2) {
608 if (state[i2] ==
'G' && fromEdges[i1] == toEdges[i2]) {
609 followsChosen =
true;
624 const std::vector<bool>& isTurnaround,
625 const std::vector<int>& fromLanes,
626 const std::vector<bool>& hadGreenMajor,
627 bool& haveForbiddenLeftMover,
628 std::vector<bool>& rightTurnConflicts) {
630 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
631 if (state[i1] ==
'G') {
632 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
633 if ((state[i2] ==
'G' || state[i2] ==
'g')) {
635 fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
636 rightTurnConflicts[i1] =
true;
638 if (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true, controlledWithin) || rightTurnConflicts[i1]) {
641 if (!isTurnaround[i1] && !hadGreenMajor[i1]) {
642 haveForbiddenLeftMover =
true;
648 if (state[i1] ==
'r') {
650 fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) ==
LINKDIR_RIGHT) {
653 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
654 if (state[i2] ==
'G' && !isTurnaround[i2] &&
655 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
656 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
657 const LinkDirection foeDir = fromEdges[i2]->getToNode()->getDirection(fromEdges[i2], toEdges[i2]);
664 if (state[i1] ==
's') {
666 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
667 if (state[i2] ==
'G' && !isTurnaround[i2] &&
668 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
669 forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
683 const std::vector<NBNode::Crossing*>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
684 const int vehLinks = noLinksAll - (int)crossings.size();
685 std::vector<bool> foundGreen(crossings.size(),
false);
686 const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->
getPhases();
687 for (
int i = 0; i < (int)phases.size(); ++i) {
688 const std::string state = phases[i].state;
689 for (
int j = 0; j < (int)crossings.size(); ++j) {
692 foundGreen[j] =
true;
696 for (
int j = 0; j < (int)foundGreen.size(); ++j) {
697 if (!foundGreen[j]) {
700 if (phases.size() > 0) {
701 bool needYellowPhase =
false;
702 std::string state = phases.back().state;
703 for (
int i1 = 0; i1 < vehLinks; ++i1) {
704 if (state[i1] ==
'G' || state[i1] ==
'g') {
706 needYellowPhase =
true;
710 if (needYellowPhase && brakingTime > 0) {
711 logic->
addStep(brakingTime, state);
723 if (allRedTime > 0) {
725 std::string allRedState = state;
726 for (
int i1 = 0; i1 < (int)state.size(); ++i1) {
727 if (allRedState[i1] ==
'Y' || allRedState[i1] ==
'y') {
728 allRedState[i1] =
'r';
731 logic->
addStep(allRedTime, allRedState);
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
The link is a partial left direction.
The link has green light, may pass.
virtual void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
bool setControllingTLInformation(const NBConnection &c, const std::string &tlID)
Returns if the link could be set as to be controlled.
TrafficLightType myType
The algorithm type for the traffic light.
void collectAllLinks()
helper method for use in NBOwnTLDef and NBLoadedSUMOTLDef
static const std::string DummyID
id for temporary definitions
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::vector< Connection > getConnectionsFromLane(int lane) const
Returns connections from a given lane.
RightOnRedConflicts myRightOnRedConflicts
A SUMO-compliant built logic for a traffic light.
TrafficLightType getType() const
get the algorithm type (static etc..)
The link has green light, has to brake.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getProgramID() const
Returns the ProgramID.
std::string correctConflicting(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges, const std::vector< bool > &isTurnaround, const std::vector< int > &fromLanes, const std::vector< bool > &hadGreenMajor, bool &haveForbiddenLeftMover, std::vector< bool > &rightTurnConflicts)
change 'G' to 'g' for conflicting connections
The representation of a single edge during network building.
std::string allowFollowersOfChosen(std::string state, const EdgeVector &fromEdges, const EdgeVector &toEdges)
allow connections that follow on of the chosen edges
bool mayBeTLSControlled(int fromLane, NBEdge *toEdge, int toLane) const
return true if certain connection must be controlled by TLS
std::string time2string(SUMOTime t)
The base class for traffic light logic definitions.
static const SUMOTime UNSPECIFIED_DURATION
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
bool isForbidden(SVCPermissions permissions)
Returns whether an edge with the given permission is a forbidden edge.
const EdgeVector & getIncomingEdges() const
Returns the list of incoming edges (must be build first)
static EdgeVector getConnectedOuterEdges(const EdgeVector &incoming)
get edges that have connections
SUMOTime myOffset
The offset in the program.
NBEdge * getFrom() const
returns the from-edge (start of the connection)
The link is a (hard) left direction.
#define WRITE_WARNING(msg)
std::pair< NBEdge *, NBEdge * > getBestPair(EdgeVector &incoming)
Returns the combination of two edges from the given which has most unblocked streams.
static OptionsCont & getOptions()
Retrieves the options.
static bool rightTurnConflict(const NBEdge *from, const NBEdge *to, int fromLane, const NBEdge *prohibitorFrom, const NBEdge *prohibitorTo, int prohibitorFromLane, bool lefthand=false)
return whether the given laneToLane connection is a right turn which must yield to a bicycle crossing...
LinkDirection
The different directions a link between two lanes may take (or a stream between two edges)...
The link is a straight direction.
const std::string & getID() const
Returns the id.
static std::string addPedestrianPhases(NBTrafficLightLogic *logic, SUMOTime greenTime, SUMOTime minDur, SUMOTime maxDur, std::string state, const std::vector< NBNode::Crossing * > &crossings, const EdgeVector &fromEdges, const EdgeVector &toEdges)
add 1 or 2 phases depending on the presence of pedestrian crossings
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
static void addPedestrianScramble(NBTrafficLightLogic *logic, int noLinksAll, SUMOTime greenTime, SUMOTime yellowTime, const std::vector< NBNode::Crossing * > &crossings, const EdgeVector &fromEdges, const EdgeVector &toEdges)
add an additional pedestrian phase if there are crossings that did not get green yet ...
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.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces a removed edge/lane.
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...
std::pair< NBEdge *, NBEdge * > getBestCombination(const EdgeVector &edges)
Returns the combination of two edges from the given which has most unblocked streams.
bool myHaveSinglePhase
Whether left-mover should not have an additional phase.
int getNumLanes() const
Returns the number of lanes.
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
The link is a (hard) right direction.
static const std::string DefaultProgramID
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
The link is a partial right direction.
SUMOTime getDuration() const
Returns the duration of the complete cycle.
void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic *logic, const std::string &state)
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
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.
void closeBuilding(bool checkVarDurations=true)
closes the building process
bool myRightOnRedConflictsReady
NBOwnTLDef(const std::string &id, const std::vector< NBNode * > &junctions, SUMOTime offset, TrafficLightType type)
Constructor.
NBNode * getToNode() const
Returns the destination node of the edge.
NBTrafficLightLogic * myCompute(int brakingTimeSeconds)
Computes the traffic light logic finally in dependence to the type.
NBTrafficLightLogic * computeLogicAndConts(int brakingTimeSeconds, bool onlyConts=false)
helper function for myCompute
void collectLinks()
Collects the links participating in this traffic light If a link could not be found.
bool myNeedsContRelationReady
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
const NBNode * node
The parent node of this crossing.
NeedsContRelation myNeedsContRelation
void setPhaseDuration(int phaseIndex, SUMOTime duration)
Modifies the duration for an existing phase (used by NETEDIT)
double getDirectionalWeight(LinkDirection dir)
Returns the weight of a stream given its direction.
EdgeVector edges
The edges being crossed.
Represents a single node (junction) during network building.
A definition of a pedestrian crossing.
void initNeedsContRelation() const
data structure for caching needsCont information
std::vector< NBNode * > myControlledNodes
The container with participating nodes.
static bool hasCrossing(const NBEdge *from, const NBEdge *to, const std::vector< NBNode::Crossing * > &crossings)
compute whether the given connection is crossed by pedestrians
A traffic light logics which must be computed (only nodes/edges are given)
void addStep(SUMOTime duration, const std::string &state, int index=-1)
Adds a phase to the logic.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
Sorts edges by their priority within the node they end at.
void setTLControllingInformation() const
Informs edges about being controlled by a tls.
NBConnectionVector myControlledLinks
The list of controlled links.
NBEdge * getTurnDestination(bool possibleDestination=false) const
int getToPrio(const NBEdge *const e)
Returns this edge's priority at the node it ends at.
void remapRemoved(NBEdge *removed, const EdgeVector &incoming, const EdgeVector &outgoing)
Replaces occurences of the removed edge in incoming/outgoing edges of all definitions.
NBNode * getFromNode() const
Returns the origin node of the edge.