/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2002-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 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#ifdef HAVE_FOX40#include <utils/foxtools/fxheader.h>41#endif42#include <utils/vehicle/SUMOVTypeParameter.h>43#include "RONode.h"44#include "ROVehicle.h"45#include <utils/router/FlippedEdge.h>464748// ===========================================================================49// class declarations50// ===========================================================================51class ROLane;52class ROEdge;5354typedef std::vector<ROEdge*> ROEdgeVector;55typedef std::vector<const ROEdge*> ConstROEdgeVector;56typedef std::vector<std::pair<const ROEdge*, const ROEdge*> > ROConstEdgePairVector;575859// ===========================================================================60// class definitions61// ===========================================================================62/**63* @class ROEdge64* @brief A basic edge for routing applications65*66* The edge contains two time lines, one for the travel time and one for a second67* measure which may be used for computing the costs of a route. After loading68* the weights, it is needed to call "buildTimeLines" in order to initialise69* these time lines.70*/71class ROEdge : public Named, public Parameterised {72public:73/** @brief Constructor74*75* @param[in] id The id of the edge76* @param[in] from The node the edge begins at77* @param[in] to The node the edge ends at78* @param[in] index The numeric id of the edge79*/80ROEdge(const std::string& id, RONode* from, RONode* to, int index, const int priority, const std::string& type);8182/** @brief Constructor for dummy edge, only used when building the connectivity graph **/83ROEdge(const std::string& id, const RONode* from, const RONode* to, SVCPermissions p);848586/// Destructor87virtual ~ROEdge();888990/// @name Set-up methods91//@{9293/** @brief Adds a lane to the edge while loading94*95* The lane's length is adapted. Additionally, the information about allowed/disallowed96* vehicle classes is patched using the information stored in the lane.97*98* @param[in] lane The lane to add99* @todo What about vehicle-type aware connections?100*/101virtual void addLane(ROLane* lane);102103104/** @brief Adds information about a connected edge105*106* The edge s is added to "myFollowingEdges" and this edge is added as predecessor to s.107* @param[in] s The edge to add108* @todo What about vehicle-type aware connections?109*/110virtual void addSuccessor(ROEdge* s, ROEdge* via = nullptr, std::string dir = "");111112113/** @brief Sets the function of the edge114* @param[in] func The new function for the edge115*/116inline void setFunction(SumoXMLEdgeFunc func) {117myFunction = func;118}119120121/** @brief Sets whether the edge is a source122* @param[in] func The new source functionality for the edge123*/124inline void setSource(const bool isSource = true) {125myAmSource = isSource;126}127128129/** @brief Sets whether the edge is a sink130* @param[in] func The new sink functionality for the edge131*/132inline void setSink(const bool isSink = true) {133myAmSink = isSink;134}135136137/** @brief Sets the vehicle class specific speed limits of the edge138* @param[in] restrictions The restrictions for the edge139*/140inline void setRestrictions(const std::map<SUMOVehicleClass, double>* restrictions) {141myRestrictions = restrictions;142}143144inline void setTimePenalty(double value) {145myTimePenalty = value;146}147148inline double getTimePenalty() const {149return myTimePenalty;150}151152/// @brief return whether this edge is a normal edge153inline bool isNormal() const {154return myFunction == SumoXMLEdgeFunc::NORMAL;155}156157/// @brief return whether this edge is an internal edge158inline bool isInternal() const {159return myFunction == SumoXMLEdgeFunc::INTERNAL;160}161162/// @brief return whether this edge is a pedestrian crossing163inline bool isCrossing() const {164return myFunction == SumoXMLEdgeFunc::CROSSING;165}166167/// @brief return whether this edge is walking area168inline bool isWalkingArea() const {169return myFunction == SumoXMLEdgeFunc::WALKINGAREA;170}171172inline bool isTazConnector() const {173return myFunction == SumoXMLEdgeFunc::CONNECTOR;174}175176void setOtherTazConnector(const ROEdge* edge) {177myOtherTazConnector = edge;178}179180const ROEdge* getOtherTazConnector() const {181return myOtherTazConnector;182}183184/** @brief Builds the internal representation of the travel time/effort185*186* Should be called after weights / travel times have been loaded.187*188* In the case "weight-attribute" is one of "CO", "CO2", "HC", "NOx", "PMx", "fuel", or "electricity"189* the proper value (departs/s) is computed and multiplied with the travel time.190*191* @param[in] measure The name of the measure to use.192*/193void buildTimeLines(const std::string& measure, const bool boundariesOverride);194195void cacheParamRestrictions(const std::vector<std::string>& restrictionKeys);196//@}197198199200/// @name Getter methods201//@{202203/** @brief Returns the function of the edge204* @return This edge's basic function205* @see SumoXMLEdgeFunc206*/207inline SumoXMLEdgeFunc getFunction() const {208return myFunction;209}210211212/** @brief Returns whether the edge acts as a sink213* @return whether the edge is a sink214*/215inline bool isSink() const {216return myAmSink;217}218219220/** @brief Returns the length of the edge221* @return This edge's length222*/223double getLength() const {224return myLength;225}226227/** @brief Returns the index (numeric id) of the edge228* @return This edge's numerical id229*/230int getNumericalID() const {231return myIndex;232}233234235/** @brief Returns the speed allowed on this edge236* @return The speed allowed on this edge237*/238double getSpeedLimit() const {239return mySpeed;240}241242/// @brief return a lower bound on shape.length() / myLength that is243// sufficient for the astar air-distance heuristic244double getLengthGeometryFactor() const;245246/** @brief Returns the lane's maximum speed, given a vehicle's speed limit adaptation247* @param[in] The vehicle to return the adapted speed limit for248* @return This lane's resulting max. speed249*/250inline double getVClassMaxSpeed(SUMOVehicleClass vclass) const {251if (myRestrictions != 0) {252std::map<SUMOVehicleClass, double>::const_iterator r = myRestrictions->find(vclass);253if (r != myRestrictions->end()) {254return r->second;255}256}257return mySpeed;258}259260261/** @brief Returns the number of lanes this edge has262* @return This edge's number of lanes263*/264int getNumLanes() const {265return (int) myLanes.size();266}267268269/** @brief returns the information whether this edge is directly connected to the given270*271* @param[in] e The edge which may be connected272* @param[in] vClass The vehicle class for which the connectivity is checked273* @return Whether the given edge is a direct successor to this one274*/275bool isConnectedTo(const ROEdge& e, const SUMOVehicleClass vClass, bool ignoreTransientPermissions = false) const;276277278/** @brief Returns whether this edge prohibits the given vehicle to pass it279* @param[in] vehicle The vehicle for which the information has to be returned280* @return Whether the vehicle must not enter this edge281*/282inline bool prohibits(const ROVehicle* const vehicle) const {283const SUMOVehicleClass vclass = vehicle->getVClass();284return (myCombinedPermissions & vclass) != vclass;285}286287inline SVCPermissions getPermissions() const {288return myCombinedPermissions;289}290291/** @brief Returns whether this edge has restriction parameters forbidding the given vehicle to pass it292* @param[in] vehicle The vehicle for which the information has to be returned293* @return Whether the vehicle must not enter this edge294*/295inline bool restricts(const ROVehicle* const vehicle) const {296const std::vector<double>& vTypeRestrictions = vehicle->getType()->paramRestrictions;297assert(vTypeRestrictions.size() == myParamRestrictions.size());298for (int i = 0; i < (int)vTypeRestrictions.size(); i++) {299if (vTypeRestrictions[i] > myParamRestrictions[i]) {300return true;301}302}303return false;304}305306307/** @brief Returns whether this edge succeeding edges prohibit the given vehicle to pass them308* @param[in] vehicle The vehicle for which the information has to be returned309* @return Whether the vehicle may continue its route on any of the following edges310*/311bool allFollowersProhibit(const ROVehicle* const vehicle) const;312//@}313314315316/// @name Methods for getting/setting travel time and cost information317//@{318319/** @brief Adds a weight value320*321* @param[in] value The value to add322* @param[in] timeBegin The begin time of the interval the given value is valid for [s]323* @param[in] timeEnd The end time of the interval the given value is valid for [s]324*/325void addEffort(double value, double timeBegin, double timeEnd);326327328/** @brief Adds a travel time value329*330* @param[in] value The value to add331* @param[in] timeBegin The begin time of the interval the given value is valid for [s]332* @param[in] timeEnd The end time of the interval the given value is valid for [s]333*/334void addTravelTime(double value, double timeBegin, double timeEnd);335336337/** @brief Returns the number of edges this edge is connected to338*339* If this edge's type is set to "sink", 0 is returned, otherwise340* the number of edges stored in "myFollowingEdges".341*342* @return The number of edges following this edge343*/344int getNumSuccessors() const;345346347/** @brief Returns the following edges, restricted by vClass348* @param[in] vClass The vClass for which to restrict the successors349* @return The eligible following edges350*/351const ROEdgeVector& getSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;352353/** @brief Returns the following edges including vias, restricted by vClass354* @param[in] vClass The vClass for which to restrict the successors355* @return The eligible following edges356*/357const ROConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;358359360/** @brief Returns the number of edges connected to this edge361*362* If this edge's type is set to "source", 0 is returned, otherwise363* the number of edges stored in "myApproachingEdges".364*365* @return The number of edges reaching into this edge366*/367int getNumPredecessors() const;368369370/** @brief Returns the edge at the given position from the list of incoming edges371* @param[in] pos The position of the list within the list of incoming372* @return The incoming edge, stored at position pos373*/374const ROEdgeVector& getPredecessors() const {375return myApproachingEdges;376}377378/// @brief if this edge is an internal edge, return its first normal predecessor, otherwise the edge itself379const ROEdge* getNormalBefore() const;380381/// @brief if this edge is an internal edge, return its first normal successor, otherwise the edge itself382const ROEdge* getNormalAfter() const;383384/** @brief Returns the effort for this edge385*386* @param[in] veh The vehicle for which the effort on this edge shall be retrieved387* @param[in] time The tim for which the effort shall be returned [s]388* @return The effort needed by the given vehicle to pass the edge at the given time389* @todo Recheck whether the vehicle's maximum speed is considered390*/391double getEffort(const ROVehicle* const veh, double time) const;392393394/** @brief Returns whether a travel time for this edge was loaded395*396* @param[in] time The time for which the travel time shall be returned [s]397* @return whether a value was loaded398*/399bool hasLoadedTravelTime(double time) const;400401402/** @brief Returns the travel time for this edge403*404* @param[in] veh The vehicle for which the travel time on this edge shall be retrieved405* @param[in] time The time for which the travel time shall be returned [s]406* @return The travel time needed by the given vehicle to pass the edge at the given time407*/408double getTravelTime(const ROVehicle* const veh, double time) const;409410411/** @brief Returns the effort for the given edge412*413* @param[in] edge The edge for which the effort shall be retrieved414* @param[in] veh The vehicle for which the effort on this edge shall be retrieved415* @param[in] time The time for which the effort shall be returned [s]416* @return The effort needed by the given vehicle to pass the edge at the given time417* @todo Recheck whether the vehicle's maximum speed is considered418*/419static inline double getEffortStatic(const ROEdge* const edge, const ROVehicle* const veh, double time) {420return edge->getEffort(veh, time);421}422423424/** @brief Returns the travel time for the given edge425*426* @param[in] edge The edge for which the travel time shall be retrieved427* @param[in] veh The vehicle for which the travel time on this edge shall be retrieved428* @param[in] time The time for which the travel time shall be returned [s]429* @return The traveltime needed by the given vehicle to pass the edge at the given time430*/431static inline double getTravelTimeStatic(const ROEdge* const edge, const ROVehicle* const veh, double time) {432return edge->getTravelTime(veh, time);433}434435static inline double getTravelTimeStaticRandomized(const ROEdge* const edge, const ROVehicle* const veh, double time) {436return edge->getTravelTime(veh, time) * RandHelper::rand(1., gWeightsRandomFactor);437}438439/// @brief Alias for getTravelTimeStatic (there is no routing device to provide aggregated travel times)440static inline double getTravelTimeAggregated(const ROEdge* const edge, const ROVehicle* const veh, double time) {441return edge->getTravelTime(veh, time);442}443444/// @brief Return traveltime weighted by edge priority (scaled penalty for low-priority edges)445static inline double getTravelTimeStaticPriorityFactor(const ROEdge* const edge, const ROVehicle* const veh, double time) {446double result = edge->getTravelTime(veh, time);447// lower priority should result in higher effort (and the edge with448// minimum priority receives a factor of myPriorityFactor449const double relativeInversePrio = 1 - ((edge->getPriority() - myMinEdgePriority) / myEdgePriorityRange);450result *= 1 + relativeInversePrio * myPriorityFactor;451return result;452}453454/** @brief Returns a lower bound for the travel time on this edge without using any stored timeLine455*456* @param[in] veh The vehicle for which the effort on this edge shall be retrieved457* @param[in] time The time for which the effort shall be returned [s]458*/459inline double getMinimumTravelTime(const ROVehicle* const veh) const {460if (isTazConnector()) {461return 0;462} else if (veh != 0) {463return myLength / MIN2(veh->getType()->maxSpeed, veh->getChosenSpeedFactor() * getVClassMaxSpeed(veh->getVClass()));464} else {465return myLength / mySpeed;466}467}468469470template<PollutantsInterface::EmissionType ET>471static double getEmissionEffort(const ROEdge* const edge, const ROVehicle* const veh, double time) {472double ret = 0;473if (!edge->getStoredEffort(time, ret)) {474const SUMOVTypeParameter* const type = veh->getType();475const double vMax = MIN2(type->maxSpeed, edge->getVClassMaxSpeed(veh->getVClass()));476const double accel = type->getCFParam(SUMO_ATTR_ACCEL, SUMOVTypeParameter::getDefaultAccel(type->vehicleClass)) * type->getCFParam(SUMO_ATTR_SIGMA, SUMOVTypeParameter::getDefaultImperfection(type->vehicleClass)) / 2.;477ret = PollutantsInterface::computeDefault(type->emissionClass, ET, vMax, accel, 0, edge->getTravelTime(veh, time), nullptr); // @todo: give correct slope478}479return ret;480}481482483static double getNoiseEffort(const ROEdge* const edge, const ROVehicle* const veh, double time);484485static double getStoredEffort(const ROEdge* const edge, const ROVehicle* const /*veh*/, double time) {486double ret = 0;487edge->getStoredEffort(time, ret);488return ret;489}490//@}491492493/// @brief optimistic distance heuristic for use in routing494double getDistanceTo(const ROEdge* other, const bool doBoundaryEstimate = false) const;495496497/** @brief Returns all ROEdges */498static const ROEdgeVector& getAllEdges();499500static void setGlobalOptions(const bool interpolate) {501myInterpolate = interpolate;502}503504static void disableTimelineWarning() {505myHaveTTWarned = true;506}507508/// @brief return the coordinates of the center of the given stop509static const Position getStopPosition(const SUMOVehicleParameter::Stop& stop);510511/// @brief get edge priority (road class)512int getPriority() const {513return myPriority;514}515516/// @brief get edge type517const std::string& getType() const {518return myType;519}520521const RONode* getFromJunction() const {522return myFromJunction;523}524525const RONode* getToJunction() const {526return myToJunction;527}528529/** @brief Returns this edge's lanes530*531* @return This edge's lanes532*/533const std::vector<ROLane*>& getLanes() const {534return myLanes;535}536537/// @brief return opposite superposable/congruent edge, if it exist and 0 else538inline const ROEdge* getBidiEdge() const {539return myBidiEdge;540}541542/// @brief set opposite superposable/congruent edge543inline void setBidiEdge(const ROEdge* bidiEdge) {544myBidiEdge = bidiEdge;545}546547ReversedEdge<ROEdge, ROVehicle>* getReversedRoutingEdge() const {548if (myReversedRoutingEdge == nullptr) {549myReversedRoutingEdge = new ReversedEdge<ROEdge, ROVehicle>(this);550}551return myReversedRoutingEdge;552}553554/// @brief Returns the flipped routing edge555// @note If not called before, the flipped routing edge is created556FlippedEdge<ROEdge, RONode, ROVehicle>* getFlippedRoutingEdge() const {557if (myFlippedRoutingEdge == nullptr) {558myFlippedRoutingEdge = new FlippedEdge<ROEdge, RONode, ROVehicle>(this);559}560return myFlippedRoutingEdge;561}562563RailEdge<ROEdge, ROVehicle>* getRailwayRoutingEdge() const {564if (myRailwayRoutingEdge == nullptr) {565myRailwayRoutingEdge = new RailEdge<ROEdge, ROVehicle>(this);566}567return myRailwayRoutingEdge;568}569570/// @brief whether effort data was loaded for this edge571bool hasStoredEffort() const {572return myUsingETimeLine;573}574575/// @brief initialize priority factor range576static bool initPriorityFactor(double priorityFactor);577578protected:579/** @brief Retrieves the stored effort580*581* @param[in] veh The vehicle for which the effort on this edge shall be retrieved582* @param[in] time The tim for which the effort shall be returned583* @return Whether the effort is given584*/585bool getStoredEffort(double time, double& ret) const;586587588589protected:590/// @brief the junctions for this edge591RONode* myFromJunction;592RONode* myToJunction;593594/// @brief The index (numeric id) of the edge595const int myIndex;596597/// @brief The edge priority (road class)598const int myPriority;599600/// @brief the type of this edge601const std::string myType;602603/// @brief The maximum speed allowed on this edge604double mySpeed;605606/// @brief The length of the edge607double myLength;608609/// @brief whether the edge is a source or a sink610bool myAmSink, myAmSource;611/// @brief Container storing passing time varying over time for the edge612mutable ValueTimeLine<double> myTravelTimes;613/// @brief Information whether the time line shall be used instead of the length value614bool myUsingTTTimeLine;615616/// @brief Container storing passing time varying over time for the edge617mutable ValueTimeLine<double> myEfforts;618/// @brief Information whether the time line shall be used instead of the length value619bool myUsingETimeLine;620621/// @brief Information whether to interpolate at interval boundaries622static bool myInterpolate;623624/// @brief Information whether the edge has reported missing weights625static bool myHaveEWarned;626/// @brief Information whether the edge has reported missing weights627static bool myHaveTTWarned;628629/// @brief List of edges that may be approached from this edge630ROEdgeVector myFollowingEdges;631632ROConstEdgePairVector myFollowingViaEdges;633634/// @brief List of edges that approached this edge635ROEdgeVector myApproachingEdges;636637/// @brief The function of the edge638SumoXMLEdgeFunc myFunction;639640/// The vClass speed restrictions for this edge641const std::map<SUMOVehicleClass, double>* myRestrictions;642643/// @brief This edge's lanes644std::vector<ROLane*> myLanes;645646/// @brief The list of allowed vehicle classes combined across lanes647SVCPermissions myCombinedPermissions;648649/// @brief the other taz-connector if this edge isTazConnector, otherwise nullptr650const ROEdge* myOtherTazConnector;651652/// @brief the bidirectional rail edge or nullpr653const ROEdge* myBidiEdge;654655/// @brief The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start and end node for normal edges656Boundary myBoundary;657658/// @brief flat penalty when computing traveltime659double myTimePenalty;660661/// @brief cached value of parameters which may restrict access662std::vector<double> myParamRestrictions;663664static ROEdgeVector myEdges;665666/// @brief Coefficient for factoring edge priority into routing weight667static double myPriorityFactor;668/// @brief Minimum priority for all edges669static double myMinEdgePriority;670/// @brief the difference between maximum and minimum priority for all edges671static double myEdgePriorityRange;672673/// @brief The successors available for a given vClass674mutable std::map<SUMOVehicleClass, ROEdgeVector> myClassesSuccessorMap;675676/// @brief The successors with vias available for a given vClass677mutable std::map<SUMOVehicleClass, ROConstEdgePairVector> myClassesViaSuccessorMap;678679/// @brief a reversed version for backward routing680mutable ReversedEdge<ROEdge, ROVehicle>* myReversedRoutingEdge = nullptr;681/// @brief An extended version of the reversed edge for backward routing (used for the arc flag router)682mutable FlippedEdge<ROEdge, RONode, ROVehicle>* myFlippedRoutingEdge = nullptr;683mutable RailEdge<ROEdge, ROVehicle>* myRailwayRoutingEdge = nullptr;684685#ifdef HAVE_FOX686/// The mutex used to avoid concurrent updates of myClassesSuccessorMap687mutable FXMutex myLock;688#endif689690private:691/// @brief Invalidated copy constructor692ROEdge(const ROEdge& src);693694/// @brief Invalidated assignment operator695ROEdge& operator=(const ROEdge& src);696697};698699700