47 #define MIN_GREEN_TIME 5 53 const std::vector<NBNode*>& junctions,
SUMOTime offset,
56 myHaveSinglePhase(false) {
102 for (
int e1l = 0; e1l < e1->
getNumLanes(); e1l++) {
104 for (
int e2l = 0; e2l < e2->
getNumLanes(); e2l++) {
106 for (std::vector<NBEdge::Connection>::iterator e1c = approached1.begin(); e1c != approached1.end(); ++e1c) {
110 for (std::vector<NBEdge::Connection>::iterator e2c = approached2.begin(); e2c != approached2.end(); ++e2c) {
114 if (!
forbids(e1, (*e1c).toEdge, e2, (*e2c).toEdge,
true)) {
126 std::pair<NBEdge*, NBEdge*>
128 std::pair<NBEdge*, NBEdge*> bestPair(static_cast<NBEdge*>(0), static_cast<NBEdge*>(0));
129 double bestValue = -1;
130 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
131 for (EdgeVector::const_iterator j = i + 1; j != edges.end(); ++j) {
133 if (value > bestValue) {
135 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
136 }
else if (value == bestValue) {
138 const double oa =
GeomHelper::getMinAngleDiff(bestPair.first->getAngleAtNode(bestPair.first->getToNode()), bestPair.second->getAngleAtNode(bestPair.second->getToNode()));
140 if (bestPair.first->getID() < (*i)->getID()) {
141 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
143 }
else if (oa < ca) {
144 bestPair = std::pair<NBEdge*, NBEdge*>(*i, *j);
153 std::pair<NBEdge*, NBEdge*>
155 if (incoming.size() == 1) {
157 std::pair<NBEdge*, NBEdge*> ret(*incoming.begin(),
static_cast<NBEdge*
>(0));
165 used.push_back(*incoming.begin());
168 for (EdgeVector::iterator i = incoming.begin() + 1; i != incoming.end() && prio ==
getToPrio(*i); ++i) {
172 if (used.size() < 2) {
176 incoming.erase(find(incoming.begin(), incoming.end(), ret.first));
177 incoming.erase(find(incoming.begin(), incoming.end(), ret.second));
195 std::vector<bool> isTurnaround;
196 std::vector<int> fromLanes;
199 for (
int i1 = 0; i1 < (int)incoming.size(); i1++) {
200 int noLanes = incoming[i1]->getNumLanes();
201 noLanesAll += noLanes;
202 for (
int i2 = 0; i2 < noLanes; i2++) {
203 NBEdge* fromEdge = incoming[i1];
205 noLinksAll += (int) approached.size();
206 for (
int i3 = 0; i3 < (int)approached.size(); i3++) {
207 if (!fromEdge->
mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
211 assert(i3 < (
int)approached.size());
212 NBEdge* toEdge = approached[i3].toEdge;
213 fromEdges.push_back(fromEdge);
214 fromLanes.push_back((
int)i2);
215 toEdges.push_back(toEdge);
219 isTurnaround.push_back(
true);
225 std::vector<NBNode::Crossing> crossings;
227 const std::vector<NBNode::Crossing>& c = (*i)->getCrossings();
230 (*i)->setCrossingTLIndices(
getID(), noLinksAll);
232 copy(c.begin(), c.end(), std::back_inserter(crossings));
233 noLinksAll += (int)c.size();
241 std::vector<int> greenPhases;
242 std::vector<bool> hadGreenMajor(noLinksAll,
false);
243 while (toProc.size() > 0) {
244 std::pair<NBEdge*, NBEdge*> chosen;
245 if (incoming.size() == 2) {
248 double angle = fabs(
NBHelpers::relAngle(incoming[0]->getAngleAtNode(incoming[0]->getToNode()), incoming[1]->getAngleAtNode(incoming[1]->getToNode())));
251 chosen = std::pair<NBEdge*, NBEdge*>(toProc[0],
static_cast<NBEdge*
>(0));
252 toProc.erase(toProc.begin());
260 std::string state((
int) noLinksAll,
'r');
263 for (
int i1 = 0; i1 < (int) incoming.size(); ++i1) {
264 NBEdge* fromEdge = incoming[i1];
265 const bool inChosen = fromEdge == chosen.first || fromEdge == chosen.second;
267 for (
int i2 = 0; i2 < numLanes; i2++) {
269 for (
int i3 = 0; i3 < (int)approached.size(); ++i3) {
270 if (!fromEdge->
mayBeTLSControlled(i2, approached[i3].toEdge, approached[i3].toLane)) {
285 for (
int i1 = 0; i1 < pos; ++i1) {
286 if (state[i1] ==
'G') {
291 if (state[i2] ==
'G' && !isTurnaround[i2] &&
292 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
296 if (!isForbidden && !
hasCrossing(fromEdges[i1], toEdges[i1], crossings)) {
302 bool haveForbiddenLeftMover =
false;
303 std::vector<bool> rightTurnConflicts(pos,
false);
304 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
305 for (
int i1 = 0; i1 < pos; ++i1) {
306 if (state[i1] ==
'G') {
307 hadGreenMajor[i1] =
true;
311 const std::string vehicleState = state;
312 greenPhases.push_back((
int)logic->
getPhases().size());
315 for (
int i1 = pos; i1 < pos + (int)crossings.size(); ++i1) {
318 const bool buildLeftGreenPhase = haveForbiddenLeftMover && !
myHaveSinglePhase && leftTurnTime > 0;
319 if (brakingTime > 0) {
321 for (
int i1 = 0; i1 < pos; ++i1) {
322 if (state[i1] !=
'G' && state[i1] !=
'g') {
325 if ((vehicleState[i1] >=
'a' && vehicleState[i1] <=
'z') && buildLeftGreenPhase && !rightTurnConflicts[i1]) {
331 logic->
addStep(brakingTime, state);
334 if (buildLeftGreenPhase) {
336 for (
int i1 = 0; i1 < pos; ++i1) {
337 if (state[i1] ==
'Y' || state[i1] ==
'y') {
341 if (state[i1] ==
'g') {
346 state =
correctConflicting(state, fromEdges, toEdges, isTurnaround, fromLanes, hadGreenMajor, haveForbiddenLeftMover, rightTurnConflicts);
349 logic->
addStep(leftTurnTime, state);
352 if (brakingTime > 0) {
353 for (
int i1 = 0; i1 < pos; ++i1) {
354 if (state[i1] !=
'G' && state[i1] !=
'g') {
360 logic->
addStep(brakingTime, state);
365 if (crossings.size() > 0) {
375 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
377 greenPhaseTime += dur;
378 minGreenDuration =
MIN2(minGreenDuration, dur);
380 const int patchSeconds = (int)(
STEPS2TIME(cycleTime - totalDuration) / greenPhases.size());
381 const int patchSecondsRest = (int)(
STEPS2TIME(cycleTime - totalDuration)) - patchSeconds * (
int)greenPhases.size();
385 || greenPhases.size() == 0) {
391 for (std::vector<int>::const_iterator it = greenPhases.begin(); it != greenPhases.end(); ++it) {
394 if (greenPhases.size() > 0) {
404 if (totalDuration > 0) {
405 if (totalDuration > 3 * (greenTime + 2 * brakingTime + leftTurnTime)) {
420 for (std::vector<NBNode::Crossing>::const_iterator it = crossings.begin(); it != crossings.end(); it++) {
424 for (EdgeVector::const_iterator it_e = cross.
edges.begin(); it_e != cross.
edges.end(); ++it_e) {
425 const NBEdge* edge = *it_e;
426 if (edge == from || edge == to) {
438 std::string state,
const std::vector<NBNode::Crossing>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
441 const std::string orig = state;
445 logic->
addStep(greenTime, state);
447 const SUMOTime pedTime = greenTime - pedClearingTime;
448 if (pedTime >= minPedTime) {
450 const int pedStates = (int)crossings.size();
451 logic->
addStep(pedTime, state);
452 state = state.substr(0, state.size() - pedStates) + std::string(pedStates,
'r');
453 logic->
addStep(pedClearingTime, state);
457 logic->
addStep(greenTime, state);
466 std::string result = state;
467 const int pos = (int)(state.size() - crossings.size());
468 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
469 const int i1 = pos + ic;
474 if (fromEdges[i2] != 0 && toEdges[i2] != 0 && fromEdges[i2]->getToNode() == cross.
node) {
475 for (EdgeVector::const_iterator it = cross.
edges.begin(); it != cross.
edges.end(); ++it) {
478 if (state[i2] !=
'r' && (edge == fromEdges[i2] ||
494 for (
int i1 = 0; i1 < pos; ++i1) {
495 if (result[i1] ==
'G') {
496 for (
int ic = 0; ic < (int)crossings.size(); ++ic) {
498 if (fromEdges[i1] != 0 && toEdges[i1] != 0 && fromEdges[i1]->getToNode() == crossing.
node) {
499 const int i2 = pos + ic;
566 (*i)->removeTrafficLight(&dummy);
577 for (EdgeVector::iterator it = result.begin(); it != result.end();) {
578 if ((*it)->getConnections().size() == 0 || (*it)->isInnerEdge()) {
579 it = result.erase(it);
593 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
594 if (state[i1] ==
'G') {
597 bool followsChosen =
false;
598 for (
int i2 = 0; i2 < (int)fromEdges.size() && !followsChosen; ++i2) {
599 if (state[i2] ==
'G' && fromEdges[i1] == toEdges[i2]) {
600 followsChosen =
true;
615 const std::vector<bool>& isTurnaround,
616 const std::vector<int>& fromLanes,
617 const std::vector<bool>& hadGreenMajor,
618 bool& haveForbiddenLeftMover,
619 std::vector<bool>& rightTurnConflicts) {
621 for (
int i1 = 0; i1 < (int)fromEdges.size(); ++i1) {
622 if (state[i1] ==
'G') {
623 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
624 if ((state[i2] ==
'G' || state[i2] ==
'g')) {
626 fromEdges[i1], toEdges[i1], fromLanes[i1], fromEdges[i2], toEdges[i2], fromLanes[i2])) {
627 rightTurnConflicts[i1] =
true;
629 if (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true, controlledWithin) || rightTurnConflicts[i1]) {
632 if (!isTurnaround[i1] && !hadGreenMajor[i1]) {
633 haveForbiddenLeftMover =
true;
639 if (state[i1] ==
'r') {
641 fromEdges[i1]->getToNode()->getDirection(fromEdges[i1], toEdges[i1]) ==
LINKDIR_RIGHT) {
644 for (
int i2 = 0; i2 < (int)fromEdges.size(); ++i2) {
645 if (state[i2] ==
'G' && !isTurnaround[i2] &&
646 (
forbids(fromEdges[i2], toEdges[i2], fromEdges[i1], toEdges[i1],
true) ||
forbids(fromEdges[i1], toEdges[i1], fromEdges[i2], toEdges[i2],
true))) {
659 const std::vector<NBNode::Crossing>& crossings,
const EdgeVector& fromEdges,
const EdgeVector& toEdges) {
660 const int vehLinks = noLinksAll - (int)crossings.size();
661 std::vector<bool> foundGreen(crossings.size(),
false);
662 const std::vector<NBTrafficLightLogic::PhaseDefinition>& phases = logic->
getPhases();
663 for (
int i = 0; i < (int)phases.size(); ++i) {
664 const std::string state = phases[i].state;
665 for (
int j = 0; j < (int)crossings.size(); ++j) {
668 foundGreen[j] =
true;
672 for (
int j = 0; j < (int)foundGreen.size(); ++j) {
673 if (!foundGreen[j]) {
676 if (phases.size() > 0) {
677 bool needYellowPhase =
false;
678 std::string state = phases.back().state;
679 for (
int i1 = 0; i1 < vehLinks; ++i1) {
680 if (state[i1] ==
'G' || state[i1] ==
'g') {
682 needYellowPhase =
true;
686 if (needYellowPhase && brakingTime > 0) {
687 logic->
addStep(brakingTime, state);
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.
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
The link is a partial left direction.
The link has green light, may pass.
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
void closeBuilding()
closes the building process
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
void collectNodes()
Collects the nodes participating in this traffic light.
std::string time2string(SUMOTime t)
The base class for traffic light logic definitions.
static bool hasCrossing(const NBEdge *from, const NBEdge *to, const std::vector< NBNode::Crossing > &crossings)
compute whether the given connection is crossed by pedestrians
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.
virtual void collectEdges()
Build the list of participating edges.
const std::vector< PhaseDefinition > & getPhases() const
Returns the phases.
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
static std::string addPedestrianPhases(NBTrafficLightLogic *logic, SUMOTime greenTime, 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
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.
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.
bool myRightOnRedConflictsReady
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 ...
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.
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.
void setParticipantsInformation()
Builds the list of participating nodes/edges/links.
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.