/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2002-2026 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 ROEdge.h14/// @author Daniel Krajzewicz15/// @author Jakob Erdmann16/// @author Christian Roessel17/// @author Michael Behrisch18/// @author Melanie Knocke19/// @author Yun-Pang Floetteroed20/// @author Ruediger Ebendt21/// @date Sept 200222///23// A basic edge for routing applications24/****************************************************************************/25#pragma once26#include <config.h>2728#include <string>29#include <map>30#include <vector>31#include <algorithm>32#include <utils/common/Named.h>33#include <utils/common/StdDefs.h>34#include <utils/common/ValueTimeLine.h>35#include <utils/common/SUMOVehicleClass.h>36#include <utils/common/RandHelper.h>37#include <utils/emissions/PollutantsInterface.h>38#include <utils/geom/Boundary.h>39#include <utils/router/FlippedEdge.h>40#ifdef HAVE_FOX41#include <utils/foxtools/fxheader.h>42#endif43#include <utils/vehicle/SUMOVTypeParameter.h>44#include "RONet.h"45#include "RONode.h"46#include "ROVehicle.h"474849// ===========================================================================50// class declarations51// ===========================================================================52class ROLane;53class ROEdge;5455typedef std::vector<ROEdge*> ROEdgeVector;56typedef std::vector<const ROEdge*> ConstROEdgeVector;57typedef std::vector<std::pair<const ROEdge*, const ROEdge*> > ROConstEdgePairVector;585960// ===========================================================================61// class definitions62// ===========================================================================63/**64* @class ROEdge65* @brief A basic edge for routing applications66*67* The edge contains two time lines, one for the travel time and one for a second68* measure which may be used for computing the costs of a route. After loading69* the weights, it is needed to call "buildTimeLines" in order to initialise70* these time lines.71*/72class ROEdge : public Named, public Parameterised {73public:74/** @brief Constructor75*76* @param[in] id The id of the edge77* @param[in] from The node the edge begins at78* @param[in] to The node the edge ends at79* @param[in] index The numeric id of the edge80*/81ROEdge(const std::string& id, RONode* from, RONode* to, int index, const int priority, const std::string& type, const std::string& routingType);8283/** @brief Constructor for dummy edge, only used when building the connectivity graph **/84ROEdge(const std::string& id, const RONode* from, const RONode* to, SVCPermissions p);858687/// Destructor88virtual ~ROEdge();899091/// @name Set-up methods92//@{9394/** @brief Adds a lane to the edge while loading95*96* The lane's length is adapted. Additionally, the information about allowed/disallowed97* vehicle classes is patched using the information stored in the lane.98*99* @param[in] lane The lane to add100* @todo What about vehicle-type aware connections?101*/102virtual void addLane(ROLane* lane);103104105/** @brief Adds information about a connected edge106*107* The edge s is added to "myFollowingEdges" and this edge is added as predecessor to s.108* @param[in] s The edge to add109* @todo What about vehicle-type aware connections?110*/111virtual void addSuccessor(ROEdge* s, ROEdge* via = nullptr, std::string dir = "");112113114/** @brief Sets the function of the edge115* @param[in] func The new function for the edge116*/117inline void setFunction(SumoXMLEdgeFunc func) {118myFunction = func;119}120121122/** @brief Sets whether the edge is a source123* @param[in] func The new source functionality for the edge124*/125inline void setSource(const bool isSource = true) {126myAmSource = isSource;127}128129130/** @brief Sets whether the edge is a sink131* @param[in] func The new sink functionality for the edge132*/133inline void setSink(const bool isSink = true) {134myAmSink = isSink;135}136137138/** @brief Sets the vehicle class specific speed limits of the edge139* @param[in] restrictions The restrictions for the edge140*/141inline void setSpeedRestrictions(const std::map<SUMOVehicleClass, double>* restrictions) {142mySpeedRestrictions = restrictions;143}144145inline void setTimePenalty(double value) {146myTimePenalty = value;147}148149inline double getTimePenalty() const {150return myTimePenalty;151}152153/// @brief return whether this edge is a normal edge154inline bool isNormal() const {155return myFunction == SumoXMLEdgeFunc::NORMAL;156}157158/// @brief return whether this edge is an internal edge159inline bool isInternal() const {160return myFunction == SumoXMLEdgeFunc::INTERNAL;161}162163/// @brief return whether this edge is a pedestrian crossing164inline bool isCrossing() const {165return myFunction == SumoXMLEdgeFunc::CROSSING;166}167168/// @brief return whether this edge is walking area169inline bool isWalkingArea() const {170return myFunction == SumoXMLEdgeFunc::WALKINGAREA;171}172173inline bool isTazConnector() const {174return myFunction == SumoXMLEdgeFunc::CONNECTOR;175}176177void setOtherTazConnector(const ROEdge* edge) {178myOtherTazConnector = edge;179}180181const ROEdge* getOtherTazConnector() const {182return myOtherTazConnector;183}184185/** @brief Builds the internal representation of the travel time/effort186*187* Should be called after weights / travel times have been loaded.188*189* In the case "weight-attribute" is one of "CO", "CO2", "HC", "NOx", "PMx", "fuel", or "electricity"190* the proper value (departs/s) is computed and multiplied with the travel time.191*192* @param[in] measure The name of the measure to use.193*/194void buildTimeLines(const std::string& measure, const bool boundariesOverride);195196void cacheParamRestrictions(const std::vector<std::string>& restrictionKeys);197//@}198199200201/// @name Getter methods202//@{203204/** @brief Returns the function of the edge205* @return This edge's basic function206* @see SumoXMLEdgeFunc207*/208inline SumoXMLEdgeFunc getFunction() const {209return myFunction;210}211212213/** @brief Returns whether the edge acts as a sink214* @return whether the edge is a sink215*/216inline bool isSink() const {217return myAmSink;218}219220221/** @brief Returns the length of the edge222* @return This edge's length223*/224double getLength() const {225return myLength;226}227228/** @brief Returns the index (numeric id) of the edge229* @return This edge's numerical id230*/231int getNumericalID() const {232return myIndex;233}234235236/** @brief Returns the speed allowed on this edge237* @return The speed allowed on this edge238*/239double getSpeedLimit() const {240return mySpeed;241}242243/// @brief return a lower bound on shape.length() / myLength that is244// sufficient for the astar air-distance heuristic245double getLengthGeometryFactor() const;246247/** @brief Returns the number of lanes this edge has248* @return This edge's number of lanes249*/250int getNumLanes() const {251return (int) myLanes.size();252}253254255/** @brief returns the information whether this edge is directly connected to the given256*257* @param[in] e The edge which may be connected258* @param[in] vClass The vehicle class for which the connectivity is checked259* @return Whether the given edge is a direct successor to this one260*/261bool isConnectedTo(const ROEdge& e, const SUMOVehicleClass vClass, bool ignoreTransientPermissions = false) const;262263264/** @brief Returns whether this edge prohibits the given vehicle to pass it265* @param[in] vehicle The vehicle for which the information has to be returned266* @return Whether the vehicle must not enter this edge267*/268inline bool prohibits(const ROVehicle* const vehicle, bool checkRestrictions = false) const {269const SUMOVehicleClass vclass = vehicle->getVClass();270return (myCombinedPermissions & vclass) != vclass || (checkRestrictions && restricts(vehicle));271}272273inline SVCPermissions getPermissions() const {274return myCombinedPermissions;275}276277/** @brief Returns whether this edge has restriction parameters forbidding the given vehicle to pass it278* @param[in] vehicle The vehicle for which the information has to be returned279* @return Whether the vehicle must not enter this edge280*/281inline bool restricts(const ROVehicle* const vehicle) const {282const std::vector<double>& vTypeRestrictions = vehicle->getType()->paramRestrictions;283assert(vTypeRestrictions.size() == myParamRestrictions.size());284for (int i = 0; i < (int)vTypeRestrictions.size(); i++) {285if (vTypeRestrictions[i] > myParamRestrictions[i]) {286return true;287}288}289return false;290}291292293/** @brief Returns whether this edge succeeding edges prohibit the given vehicle to pass them294* @param[in] vehicle The vehicle for which the information has to be returned295* @return Whether the vehicle may continue its route on any of the following edges296*/297bool allFollowersProhibit(const ROVehicle* const vehicle) const;298//@}299300301302/// @name Methods for getting/setting travel time and cost information303//@{304305/** @brief Adds a weight value306*307* @param[in] value The value to add308* @param[in] timeBegin The begin time of the interval the given value is valid for [s]309* @param[in] timeEnd The end time of the interval the given value is valid for [s]310*/311void addEffort(double value, double timeBegin, double timeEnd);312313314/** @brief Adds a travel time value315*316* @param[in] value The value to add317* @param[in] timeBegin The begin time of the interval the given value is valid for [s]318* @param[in] timeEnd The end time of the interval the given value is valid for [s]319*/320void addTravelTime(double value, double timeBegin, double timeEnd);321322323/** @brief Returns the number of edges this edge is connected to324*325* If this edge's type is set to "sink", 0 is returned, otherwise326* the number of edges stored in "myFollowingEdges".327*328* @return The number of edges following this edge329*/330int getNumSuccessors() const;331332333/** @brief Returns the following edges, restricted by vClass334* @param[in] vClass The vClass for which to restrict the successors335* @return The eligible following edges336*/337const ROEdgeVector& getSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;338339/** @brief Returns the following edges including vias, restricted by vClass340* @param[in] vClass The vClass for which to restrict the successors341* @return The eligible following edges342*/343const ROConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;344345/// @brief reset after lane permissions changes346void resetSuccessors() {347myClassesSuccessorMap.clear();348myClassesViaSuccessorMap.clear();349}350351/** @brief Returns the number of edges connected to this edge352*353* If this edge's type is set to "source", 0 is returned, otherwise354* the number of edges stored in "myApproachingEdges".355*356* @return The number of edges reaching into this edge357*/358int getNumPredecessors() const;359360361/** @brief Returns the edge at the given position from the list of incoming edges362* @param[in] pos The position of the list within the list of incoming363* @return The incoming edge, stored at position pos364*/365const ROEdgeVector& getPredecessors() const {366return myApproachingEdges;367}368369/// @brief if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself370const ROEdge* getNormalBefore() const;371372/// @brief if this edge is an internal edge, return its first normal successor, otherwise the edge itself373const ROEdge* getNormalAfter() const;374375/** @brief Returns the effort for this edge376*377* @param[in] veh The vehicle for which the effort on this edge shall be retrieved378* @param[in] time The tim for which the effort shall be returned [s]379* @return The effort needed by the given vehicle to pass the edge at the given time380* @todo Recheck whether the vehicle's maximum speed is considered381*/382double getEffort(const ROVehicle* const veh, double time) const;383384385/** @brief Returns whether a travel time for this edge was loaded386*387* @param[in] time The time for which the travel time shall be returned [s]388* @return whether a value was loaded389*/390bool hasLoadedTravelTime(double time) const;391392393/** @brief Returns the travel time for this edge394*395* @param[in] veh The vehicle for which the travel time on this edge shall be retrieved396* @param[in] time The time for which the travel time shall be returned [s]397* @return The travel time needed by the given vehicle to pass the edge at the given time398*/399double getTravelTime(const ROVehicle* const veh, double time) const;400401402/** @brief Returns the effort for the given edge403*404* @param[in] edge The edge for which the effort shall be retrieved405* @param[in] veh The vehicle for which the effort on this edge shall be retrieved406* @param[in] time The time for which the effort shall be returned [s]407* @return The effort needed by the given vehicle to pass the edge at the given time408* @todo Recheck whether the vehicle's maximum speed is considered409*/410static inline double getEffortStatic(const ROEdge* const edge, const ROVehicle* const veh, double time) {411return edge->getEffort(veh, time);412}413414415/** @brief Returns the travel time for the given edge416*417* @param[in] edge The edge for which the travel time shall be retrieved418* @param[in] veh The vehicle for which the travel time on this edge shall be retrieved419* @param[in] time The time for which the travel time shall be returned [s]420* @return The traveltime needed by the given vehicle to pass the edge at the given time421*/422static inline double getTravelTimeStatic(const ROEdge* const edge, const ROVehicle* const veh, double time) {423return edge->getTravelTime(veh, time) * getRoutingFactor(edge, veh);424}425426static inline double getTravelTimeStaticRandomized(const ROEdge* const edge, const ROVehicle* const veh, double time) {427return edge->getTravelTime(veh, time)428* (1 + RandHelper::randHash(veh->getRandomSeed() ^ edge->getNumericalID()) * (gWeightsRandomFactor - 1))429* getRoutingFactor(edge, veh);430}431432/// @brief Alias for getTravelTimeStatic (there is no routing device to provide aggregated travel times)433static inline double getTravelTimeAggregated(const ROEdge* const edge, const ROVehicle* const veh, double time) {434return edge->getTravelTime(veh, time) * getRoutingFactor(edge, veh);435}436437/// @brief Return traveltime weighted by edge priority (scaled penalty for low-priority edges)438static inline double getTravelTimeStaticPriorityFactor(const ROEdge* const edge, const ROVehicle* const veh, double time) {439double result = edge->getTravelTime(veh, time);440// lower priority should result in higher effort (and the edge with441// minimum priority receives a factor of myPriorityFactor442const double relativeInversePrio = 1 - ((edge->getPriority() - myMinEdgePriority) / myEdgePriorityRange);443result *= 1 + relativeInversePrio * myPriorityFactor;444return result * getRoutingFactor(edge, veh);445}446447static inline double getRoutingFactor(const ROEdge* const edge, const ROVehicle* const veh) {448return gRoutingPreferences ? 1 / edge->getPreference(veh->getVTypeParameter()) : 1;449}450451452/** @brief Returns a lower bound for the travel time on this edge without using any stored timeLine453*454* @param[in] veh The vehicle for which the effort on this edge shall be retrieved455* @param[in] time The time for which the effort shall be returned [s]456*/457inline double getMinimumTravelTime(const ROVehicle* const veh) const {458if (isTazConnector()) {459return 0;460} else if (veh != 0) {461return myLength / getMaxSpeed(veh);462} else {463return myLength / mySpeed;464}465}466467inline double getMaxSpeed(const RORoutable* const veh) const {468return MIN2(veh->getMaxSpeed(), veh->getChosenSpeedFactor() * getVClassMaxSpeed(veh->getVClass()));469}470471/** @brief Returns the lane's maximum speed, given a vehicle's speed limit adaptation472* @param[in] The vehicle to return the adapted speed limit for473* @return This lane's resulting max. speed474*/475inline double getVClassMaxSpeed(SUMOVehicleClass vclass) const {476if (mySpeedRestrictions != 0) {477std::map<SUMOVehicleClass, double>::const_iterator r = mySpeedRestrictions->find(vclass);478if (r != mySpeedRestrictions->end()) {479return r->second;480}481}482return mySpeed;483}484485template<PollutantsInterface::EmissionType ET>486static double getEmissionEffort(const ROEdge* const edge, const ROVehicle* const veh, double time) {487double ret = 0;488if (!edge->getStoredEffort(time, ret)) {489const SUMOVTypeParameter* const type = veh->getType();490const double vMax = edge->getMaxSpeed(veh);491const double accel = type->getCFParam(SUMO_ATTR_ACCEL, SUMOVTypeParameter::getDefaultAccel(type->vehicleClass)) * type->getCFParam(SUMO_ATTR_SIGMA, SUMOVTypeParameter::getDefaultImperfection(type->vehicleClass)) / 2.;492ret = PollutantsInterface::computeDefault(type->emissionClass, ET, vMax, accel, 0, edge->getTravelTime(veh, time), nullptr); // @todo: give correct slope493}494return ret;495}496497498static double getNoiseEffort(const ROEdge* const edge, const ROVehicle* const veh, double time);499500static double getStoredEffort(const ROEdge* const edge, const ROVehicle* const /*veh*/, double time) {501double ret = 0;502edge->getStoredEffort(time, ret);503return ret;504}505//@}506507508/// @brief optimistic distance heuristic for use in routing509double getDistanceTo(const ROEdge* other, const bool doBoundaryEstimate = false) const;510511512/** @brief Returns all ROEdges */513static const ROEdgeVector& getAllEdges();514515static void setGlobalOptions(const bool interpolate) {516myInterpolate = interpolate;517}518519static void disableTimelineWarning() {520myHaveTTWarned = true;521}522523/// @brief return the coordinates of the center of the given stop524static const Position getStopPosition(const SUMOVehicleParameter::Stop& stop);525526/// @brief return loaded edge preference based on routingType527inline double getPreference(const SUMOVTypeParameter& pars) const {528return RONet::getInstance()->getPreference(getRoutingType(), pars);529}530531/// @brief get edge priority (road class)532int getPriority() const {533return myPriority;534}535536/// @brief get edge type537const std::string& getType() const {538return myType;539}540541const std::string& getRoutingType() const {542return myRoutingType.empty() ? myType : myRoutingType;543}544545const RONode* getFromJunction() const {546return myFromJunction;547}548549const RONode* getToJunction() const {550return myToJunction;551}552553/** @brief Returns this edge's lanes554*555* @return This edge's lanes556*/557const std::vector<ROLane*>& getLanes() const {558return myLanes;559}560561/// @brief return opposite superposable/congruent edge, if it exist and 0 else562inline const ROEdge* getBidiEdge() const {563return myBidiEdge;564}565566/// @brief set opposite superposable/congruent edge567inline void setBidiEdge(const ROEdge* bidiEdge) {568myBidiEdge = bidiEdge;569}570571ReversedEdge<ROEdge, ROVehicle>* getReversedRoutingEdge() const {572if (myReversedRoutingEdge == nullptr) {573myReversedRoutingEdge = new ReversedEdge<ROEdge, ROVehicle>(this);574}575return myReversedRoutingEdge;576}577578/// @brief Returns the flipped routing edge579// @note If not called before, the flipped routing edge is created580FlippedEdge<ROEdge, RONode, ROVehicle>* getFlippedRoutingEdge() const {581if (myFlippedRoutingEdge == nullptr) {582myFlippedRoutingEdge = new FlippedEdge<ROEdge, RONode, ROVehicle>(this);583}584return myFlippedRoutingEdge;585}586587RailEdge<ROEdge, ROVehicle>* getRailwayRoutingEdge() const {588if (myRailwayRoutingEdge == nullptr) {589myRailwayRoutingEdge = new RailEdge<ROEdge, ROVehicle>(this);590}591return myRailwayRoutingEdge;592}593594/// @brief whether effort data was loaded for this edge595bool hasStoredEffort() const {596return myUsingETimeLine;597}598599/// @brief initialize priority factor range600static bool initPriorityFactor(double priorityFactor);601602protected:603/** @brief Retrieves the stored effort604*605* @param[in] veh The vehicle for which the effort on this edge shall be retrieved606* @param[in] time The tim for which the effort shall be returned607* @return Whether the effort is given608*/609bool getStoredEffort(double time, double& ret) const;610611protected:612/// @brief the junctions for this edge613RONode* myFromJunction;614RONode* myToJunction;615616/// @brief The index (numeric id) of the edge617const int myIndex;618619/// @brief The edge priority (road class)620const int myPriority;621622/// @brief the type of this edge623const std::string myType;624625/// @brief the routing type of the edge (used to look up vType and vClass specific routing preferences)626const std::string myRoutingType;627628/// @brief The maximum speed allowed on this edge629double mySpeed;630631/// @brief The length of the edge632double myLength;633634/// @brief whether the edge is a source or a sink635bool myAmSink, myAmSource;636/// @brief Container storing passing time varying over time for the edge637mutable ValueTimeLine<double> myTravelTimes;638/// @brief Information whether the time line shall be used instead of the length value639bool myUsingTTTimeLine;640641/// @brief Container storing passing time varying over time for the edge642mutable ValueTimeLine<double> myEfforts;643/// @brief Information whether the time line shall be used instead of the length value644bool myUsingETimeLine;645646/// @brief Information whether to interpolate at interval boundaries647static bool myInterpolate;648649/// @brief Information whether the edge has reported missing weights650static bool myHaveEWarned;651/// @brief Information whether the edge has reported missing weights652static bool myHaveTTWarned;653654/// @brief List of edges that may be approached from this edge655ROEdgeVector myFollowingEdges;656657ROConstEdgePairVector myFollowingViaEdges;658659/// @brief List of edges that approached this edge660ROEdgeVector myApproachingEdges;661662/// @brief The function of the edge663SumoXMLEdgeFunc myFunction;664665/// The vClass speed restrictions for this edge666const std::map<SUMOVehicleClass, double>* mySpeedRestrictions;667668/// @brief This edge's lanes669std::vector<ROLane*> myLanes;670671/// @brief The list of allowed vehicle classes combined across lanes672SVCPermissions myCombinedPermissions;673674/// @brief the other taz-connector if this edge isTazConnector, otherwise nullptr675const ROEdge* myOtherTazConnector;676677/// @brief the bidirectional rail edge or nullpr678const ROEdge* myBidiEdge;679680/// @brief The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start and end node for normal edges681Boundary myBoundary;682683/// @brief flat penalty when computing traveltime684double myTimePenalty;685686/// @brief cached value of parameters which may restrict access687std::vector<double> myParamRestrictions;688689static ROEdgeVector myEdges;690691/// @brief Coefficient for factoring edge priority into routing weight692static double myPriorityFactor;693/// @brief Minimum priority for all edges694static double myMinEdgePriority;695/// @brief the difference between maximum and minimum priority for all edges696static double myEdgePriorityRange;697698/// @brief The successors available for a given vClass699mutable std::map<SUMOVehicleClass, ROEdgeVector> myClassesSuccessorMap;700701/// @brief The successors with vias available for a given vClass702mutable std::map<SUMOVehicleClass, ROConstEdgePairVector> myClassesViaSuccessorMap;703704/// @brief a reversed version for backward routing705mutable ReversedEdge<ROEdge, ROVehicle>* myReversedRoutingEdge = nullptr;706/// @brief An extended version of the reversed edge for backward routing (used for the arc flag router)707mutable FlippedEdge<ROEdge, RONode, ROVehicle>* myFlippedRoutingEdge = nullptr;708mutable RailEdge<ROEdge, ROVehicle>* myRailwayRoutingEdge = nullptr;709710#ifdef HAVE_FOX711/// The mutex used to avoid concurrent updates of myClassesSuccessorMap712mutable FXMutex myLock;713#endif714715private:716/// @brief Invalidated copy constructor717ROEdge(const ROEdge& src);718719/// @brief Invalidated assignment operator720ROEdge& operator=(const ROEdge& src);721722};723724725