/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file NBOwnTLDef.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Sascha Krieg17/// @date Tue, 29.05.200518///19// A traffic light logics which must be computed (only nodes/edges are given)20/****************************************************************************/21#pragma once22#include <config.h>2324#include <vector>25#include <set>26#include <utils/xml/SUMOXMLDefinitions.h>27#include "NBTrafficLightDefinition.h"28#include "NBNode.h"293031// ===========================================================================32// class declarations33// ===========================================================================343536// ===========================================================================37// class definitions38// ===========================================================================39/**40* @class NBOwnTLDef41* @brief A traffic light logics which must be computed (only nodes/edges are given)42*/43class NBOwnTLDef : public NBTrafficLightDefinition {44public:45/** @brief Constructor46* @param[in] id The id of the tls47* @param[in] junctions Junctions controlled by this tls48* @param[in] offset The offset of the plan49* @param[in] type The algorithm type for the computed traffic light50*/51NBOwnTLDef(const std::string& id,52const std::vector<NBNode*>& junctions,53SUMOTime offset,54TrafficLightType type);555657/** @brief Constructor58* @param[in] id The id of the tls59* @param[in] junction The junction controlled by this tls60* @param[in] offset The offset of the plan61* @param[in] type The algorithm type for the computed traffic light62*/63NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,64TrafficLightType type);656667/** @brief Constructor68* @param[in] id The id of the tls69* @param[in] offset The offset of the plan70* @param[in] type The algorithm type for the computed traffic light71*/72NBOwnTLDef(const std::string& id, SUMOTime offset, TrafficLightType type);737475/// @brief Destructor76~NBOwnTLDef();777879/// @name Public methods from NBTrafficLightDefinition-interface80/// @{8182/** @brief Replaces occurrences of the removed edge in incoming/outgoing edges of all definitions83* @param[in] removed The removed edge84* @param[in] incoming The edges to use instead if an incoming edge was removed85* @param[in] outgoing The edges to use instead if an outgoing edge was removed86* @see NBTrafficLightDefinition::remapRemoved87*/88void remapRemoved(NBEdge* removed,89const EdgeVector& incoming, const EdgeVector& outgoing);909192/** @brief Informs edges about being controlled by a tls93* @see NBTrafficLightDefinition::setTLControllingInformation94*/95void setTLControllingInformation() const;96/// @}979899/// @brief Forces the definition not to compute an additional phase for left-movers100void setSinglePhase() {101myHaveSinglePhase = true;102}103104/// @brief ensure inner edges all get the green light eventually105static void addGreenWithin(NBTrafficLightLogic* logic, const EdgeVector& fromEdges, EdgeVector& toProc);106107/// @brief add an additional pedestrian phase if there are crossings that did not get green yet108static void addPedestrianScramble(NBTrafficLightLogic* logic, int totalNumLinks, SUMOTime greenTime, SUMOTime yellowTime,109const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);110111/// @brief add 1 or 2 phases depending on the presence of pedestrian crossings112static std::string addPedestrianPhases(NBTrafficLightLogic* logic, const SUMOTime greenTime, const SUMOTime minDur, const SUMOTime maxDur,113const SUMOTime earliestEnd, const SUMOTime latestEnd,114std::string state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);115116/// @brief compute phase state in regard to pedestrian crossings117static std::string patchStateForCrossings(const std::string& state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);118119static std::string patchNEMAStateForCrossings(const std::string& state,120const std::vector<NBNode::Crossing*>& crossings,121const EdgeVector& fromEdges,122const EdgeVector& toEdges,123const NBEdge* greenEdge, NBEdge* otherChosen);124125/** @brief helper function for myCompute126* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls127* @param[in] onlyConts whether the method is only called to compute myNeedsContRelation128* @return The computed logic129*/130NBTrafficLightLogic* computeLogicAndConts(int brakingTimeSeconds, bool onlyConts = false);131132/* initialize myNeedsContRelation and set myNeedsContRelationReady to true */133void initNeedsContRelation() const;134135/* build optional all-red phase */136void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic* logic, const std::string& state);137138///@brief Returns the maximum index controlled by this traffic light139int getMaxIndex();140141/// @brief sets the layout for the generated signal plan142void setLayout(TrafficLightLayout layout) {143myLayout = layout;144}145146TrafficLightLayout getLayout() const {147return myLayout;148}149150/// @brief minimum speed for computing time to cross intersection151static const double MIN_SPEED_CROSSING_TIME;152153protected:154/// @name Protected methods from NBTrafficLightDefinition-interface155/// @{156157/** @brief Computes the traffic light logic finally in dependence to the type158* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls159* @return The computed logic160* @see NBTrafficLightDefinition::myCompute161*/162NBTrafficLightLogic* myCompute(int brakingTimeSeconds);163164165/** @brief Collects the links participating in this traffic light166* @exception ProcessError If a link could not be found167* @see NBTrafficLightDefinition::collectLinks168*/169void collectLinks();170171172/** @brief Replaces a removed edge/lane173* @param[in] removed The edge to replace174* @param[in] removedLane The lane of this edge to replace175* @param[in] by The edge to insert instead176* @param[in] byLane This edge's lane to insert instead177* @see NBTrafficLightDefinition::replaceRemoved178*/179void replaceRemoved(NBEdge* removed, int removedLane,180NBEdge* by, int byLane, bool incoming);181/// @}182183184protected:185186/// @brief test whether a joined tls with layout 'opposites' would be built without dedicated left-turn phase187bool corridorLike() const;188189NBTrafficLightLogic* buildNemaPhases(190const EdgeVector& fromEdges,191const EdgeVector& toEdges,192const std::vector<NBNode::Crossing*>& crossings,193const std::vector<std::pair<NBEdge*, NBEdge*> >& chosenList,194const std::vector<std::string>& straightStates,195const std::vector<std::string>& leftStates);196197/// @brief mask out all greens that do not originate at the given edge198std::string filterState(std::string state, const EdgeVector& fromEdges, const NBEdge* e);199200/// @brief keep only valid NEMA phase names (for params)201void filterMissingNames(std::vector<int>& vec, const std::map<int, int>& names, bool isBarrier, int barrierDefault = 0);202203/// @brief ensure that phase max durations before each barrier have the same sum in both rings204void fixDurationSum(NBTrafficLightLogic* logic, const std::map<int, int>& names, int ring1a, int ring1b, int ring2a, int ring2b);205206/** @brief Returns the weight of a stream given its direction207* @param[in] dir The direction of the stream208* @return This stream's weight209* @todo There are several magic numbers; describe210*/211double getDirectionalWeight(LinkDirection dir);212213214/** @brief Returns this edge's priority at the node it ends at215* @param[in] e The edge to ask for his priority216* @return The edge's priority at his destination node217*/218int getToPrio(const NBEdge* const e);219220221/** @brief Returns how many streams outgoing from the edges can pass the junction without being blocked222* @param[in] e1 The first edge223* @param[in] e2 The second edge224* @todo There are several magic numbers; describe225*/226double computeUnblockedWeightedStreamNumber(const NBEdge* const e1, const NBEdge* const e2);227228229/** @brief Returns the combination of two edges from the given which has most unblocked streams230* @param[in] edges The list of edges to include in the computation231* @return The two edges for which the weighted number of unblocked streams is the highest232*/233std::pair<NBEdge*, NBEdge*> getBestCombination(const EdgeVector& edges);234235236/** @brief Returns the combination of two edges from the given which has most unblocked streams237*238* The chosen edges are removed from the given vector239*240* @param[in, changed] incoming The list of edges which are participating in the logic241* @return The two edges for which the weighted number of unblocked streams is the highest242*/243std::pair<NBEdge*, NBEdge*> getBestPair(EdgeVector& incoming);244245246/// @brief compute whether the given connection is crossed by pedestrians247static bool hasCrossing(const NBEdge* from, const NBEdge* to, const std::vector<NBNode::Crossing*>& crossings);248249/// @brief get edges that have connections250static EdgeVector getConnectedOuterEdges(const EdgeVector& incoming);251252253/// @brief allow connections that are compatible with the chosen edges254std::string allowCompatible(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,255const std::vector<int>& fromLanes, const std::vector<int>& toLanes);256257std::string allowSingleEdge(std::string state, const EdgeVector& fromEdges);258259std::string allowFollowers(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges);260261std::string allowPredecessors(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,262const std::vector<int>& fromLanes, const std::vector<int>& toLanes);263264std::string allowUnrelated(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,265const std::vector<bool>& isTurnaround,266const std::vector<NBNode::Crossing*>& crossings);267268std::string allowByVClass(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges, SVCPermissions perm);269270/// @brief whether the given index is forbidden by a green link in the current state271bool forbidden(const std::string& state, int index, const EdgeVector& fromEdges, const EdgeVector& toEdges, bool allowCont);272273/** @brief change 'G' to 'g' for conflicting connections274* @param[in] state275* @param[in] fromEdges276* @param[in] toEdges277* @param[in] isTurnaround278* @param[in] fromLanes279* @param[in] hadGreenMajor280* @param[out] haveForbiddenLeftMover281* @param[out] rightTurnConflicts282* @param[out] mergeConflicts283* @return The corrected state284*/285std::string correctConflicting(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,286const std::vector<bool>& isTurnaround,287const std::vector<int>& fromLanes,288const std::vector<int>& toLanes,289const std::vector<bool>& hadGreenMajor,290bool& haveForbiddenLeftMover,291std::vector<bool>& rightTurnConflicts,292std::vector<bool>& mergeConflicts);293294/// @brief prevent green and red from the same lane295std::string correctMixed(std::string state, const EdgeVector& fromEdges,296const std::vector<int>& fromLanes,297bool& buildMixedGreenPhase, std::vector<bool>& mixedGreen);298299/// @brief find maximum crossing index300int maxCrossingIndex(const NBNode* node) const;301302/// @brief avoid yellow signal between successive green (major) phases303void fixSuperfluousYellow(NBTrafficLightLogic* logic) const;304305/// @brief switch of signal for links that are always green306void deactivateAlwaysGreen(NBTrafficLightLogic* logic) const;307308/// @brief switch of signal for links that are inside a joined tls309void deactivateInsideEdges(NBTrafficLightLogic* logic, const EdgeVector& fromEdges) const;310311/// @brief compute time to clear all vehicles from within an alternateOneWay layout312SUMOTime computeEscapeTime(const std::string& state, const EdgeVector& fromEdges, const EdgeVector& toEdges) const;313314/// @brief check whether there is a straight connection from this edge315bool hasStraightConnection(const NBEdge* fromEdge);316317/** @class edge_by_incoming_priority_sorter318* @brief Sorts edges by their priority within the node they end at319*/320class edge_by_incoming_priority_sorter {321public:322/** @brief comparing operator323* @param[in] e1 an edge324* @param[in] e2 an edge325*/326int operator()(const NBEdge* const e1, const NBEdge* const e2) const {327if (e1->getJunctionPriority(e1->getToNode()) != e2->getJunctionPriority(e2->getToNode())) {328return e1->getJunctionPriority(e1->getToNode()) > e2->getJunctionPriority(e2->getToNode());329}330return e1->getID() > e2->getID();331}332};333334335private:336/// @brief Whether left-mover should not have an additional phase337bool myHaveSinglePhase;338339/// @brief the layout for generated signal plans340TrafficLightLayout myLayout;341342};343344345