Skip to content

Commit

Permalink
fix #13494
Browse files Browse the repository at this point in the history
  • Loading branch information
namdre committed Apr 24, 2024
1 parent 4ad3916 commit d42030e
Show file tree
Hide file tree
Showing 20 changed files with 99 additions and 35 deletions.
6 changes: 6 additions & 0 deletions src/microsim/MSBaseVehicle.cpp
Expand Up @@ -191,6 +191,12 @@ MSBaseVehicle::replaceParameter(const SUMOVehicleParameter* newParameter) {
myParameter = newParameter;
}


bool
MSBaseVehicle::ignoreTransientPermissions() const {
return (getRoutingMode() & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS) != 0;
}

double
MSBaseVehicle::getMaxSpeed() const {
return MIN2(myType->getMaxSpeed(), myType->getDesiredMaxSpeed() * myChosenSpeedFactor);
Expand Down
5 changes: 5 additions & 0 deletions src/microsim/MSBaseVehicle.h
Expand Up @@ -159,6 +159,11 @@ class MSBaseVehicle : public SUMOVehicle {
return myType->getParameter().vehicleClass;
}

/** @brief Returns whether this object is ignoring transient permission
* changes (during routing)
*/
bool ignoreTransientPermissions() const;

/** @brief Returns the maximum speed (the minimum of desired and technical maximum speed)
* @return The vehicle's maximum speed
*/
Expand Down
41 changes: 27 additions & 14 deletions src/microsim/MSEdge.cpp
Expand Up @@ -74,6 +74,7 @@ MSEdge::MSEdge(const std::string& id, int numericalID,
myLaneChanger(nullptr), myFunction(function), myVaporizationRequests(0),
myLastFailedInsertionTime(-1),
myFromJunction(nullptr), myToJunction(nullptr),
myHaveTransientPermissions(false),
myOtherTazConnector(nullptr),
myStreetName(streetName),
myEdgeType(edgeType),
Expand Down Expand Up @@ -317,13 +318,22 @@ MSEdge::rebuildAllowedLanes(const bool onInit) {
// rebuild myMinimumPermissions and myCombinedPermissions
myMinimumPermissions = SVCAll;
myCombinedPermissions = 0;
bool lanesChangedPermission = false;
for (MSLane* const lane : *myLanes) {
// same dedicated lanes are ignored in meso to avoid capacity errors.
// Here we have to make sure that vehicles which are set to depart on
// such lanes trigger an error.
SVCPermissions allow = getMesoPermissions(lane->getPermissions(), SVC_PEDESTRIAN);
myMinimumPermissions &= allow;
myCombinedPermissions |= allow;
lanesChangedPermission |= lane->hadPermissionChanges();
}
if (!onInit && !myHaveTransientPermissions && lanesChangedPermission) {
myHaveTransientPermissions = true;
// backup original structures when first needed
myOrigAllowed = myAllowed;
myOrigAllowedTargets = myAllowedTargets;
myOrigClassesViaSuccessorMap = myClassesViaSuccessorMap;
}
// rebuild myAllowed
myAllowed.clear();
Expand All @@ -347,6 +357,12 @@ MSEdge::rebuildAllowedLanes(const bool onInit) {
} else {
rebuildAllowedTargets(false);
for (MSEdge* pred : myPredecessors) {
if (myHaveTransientPermissions && !pred->myHaveTransientPermissions) {
pred->myOrigAllowed = pred->myAllowed;
pred->myOrigAllowedTargets = pred->myAllowedTargets;
pred->myOrigClassesViaSuccessorMap = pred->myClassesViaSuccessorMap;
pred->myHaveTransientPermissions = true;
}
pred->rebuildAllowedTargets(false);
}
if (MSGlobals::gUseMesoSim) {
Expand Down Expand Up @@ -455,9 +471,10 @@ MSEdge::parallelLane(const MSLane* const lane, int offset, bool includeOpposite)


const std::vector<MSLane*>*
MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass) const {
AllowedLanesByTarget::const_iterator i = myAllowedTargets.find(&destination);
if (i != myAllowedTargets.end()) {
MSEdge::allowedLanes(const MSEdge& destination, SUMOVehicleClass vclass, bool ignoreTransientPermissions) const {
const auto& targets = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigAllowedTargets : myAllowedTargets;
AllowedLanesByTarget::const_iterator i = targets.find(&destination);
if (i != targets.end()) {
for (const auto& allowed : i->second) {
if ((allowed.first & vclass) == vclass) {
return allowed.second.get();
Expand Down Expand Up @@ -1204,26 +1221,27 @@ MSEdge::getSuccessors(SUMOVehicleClass vClass) const {


const MSConstEdgePairVector&
MSEdge::getViaSuccessors(SUMOVehicleClass vClass) const {
MSEdge::getViaSuccessors(SUMOVehicleClass vClass, bool ignoreTransientPermissions) const {
if (vClass == SVC_IGNORING || !MSNet::getInstance()->hasPermissions() || myFunction == SumoXMLEdgeFunc::CONNECTOR) {
return myViaSuccessors;
}
#ifdef HAVE_FOX
ScopedLocker<> lock(mySuccessorMutex, MSGlobals::gNumThreads > 1);
#endif
auto i = myClassesViaSuccessorMap.find(vClass);
if (i != myClassesViaSuccessorMap.end()) {
auto& viaMap = ignoreTransientPermissions && myHaveTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
auto i = viaMap.find(vClass);
if (i != viaMap.end()) {
// can use cached value
return i->second;
}
// instantiate vector
MSConstEdgePairVector& result = myClassesViaSuccessorMap[vClass];
MSConstEdgePairVector& result = viaMap[vClass];
// this vClass is requested for the first time. rebuild all successors
for (const auto& viaPair : myViaSuccessors) {
if (viaPair.first->isTazConnector()) {
result.push_back(viaPair);
} else {
const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass);
const std::vector<MSLane*>* allowed = allowedLanes(*viaPair.first, vClass, ignoreTransientPermissions);
if (allowed != nullptr && allowed->size() > 0) {
result.push_back(viaPair);
}
Expand Down Expand Up @@ -1556,12 +1574,7 @@ MSEdge::getDistanceAt(double pos) const {

bool
MSEdge::hasTransientPermissions() const {
for (const MSLane* lane : *myLanes) {
if (lane->hadPermissionChanges()) {
return true;
}
}
return false;
return myHaveTransientPermissions;
}


Expand Down
13 changes: 9 additions & 4 deletions src/microsim/MSEdge.h
Expand Up @@ -40,7 +40,6 @@
#include <utils/router/RailEdge.h>
#include <utils/vehicle/SUMOVehicle.h>
#include <utils/vehicle/SUMOTrafficObject.h>
#include <libsumo/TraCIConstants.h>
#include "MSNet.h"


Expand Down Expand Up @@ -225,7 +224,7 @@ class MSEdge : public Named, public Parameterised {
* @return The lanes that may be used to reach the given edge, nullptr if no such lanes exist
*/
const std::vector<MSLane*>* allowedLanes(const MSEdge& destination,
SUMOVehicleClass vclass = SVC_IGNORING) const;
SUMOVehicleClass vclass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;



Expand Down Expand Up @@ -389,7 +388,7 @@ class MSEdge : public Named, public Parameterised {
* @param[in] vClass The vClass for which to restrict the successors
* @return The eligible following edges
*/
const MSConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;
const MSConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;


/** @brief Returns the number of edges this edge is connected to
Expand Down Expand Up @@ -607,7 +606,7 @@ class MSEdge : public Named, public Parameterised {
return false;
}
const SUMOVehicleClass svc = vehicle->getVClass();
return ((vehicle->getRoutingMode() & libsumo::ROUTING_MODE_IGNORE_TRANSIENT_PERMISSIONS)
return (vehicle->ignoreTransientPermissions()
? (myOriginalCombinedPermissions & svc) != svc
: (myCombinedPermissions & svc) != svc);
}
Expand Down Expand Up @@ -920,9 +919,11 @@ class MSEdge : public Named, public Parameterised {

/// @brief Associative container from vehicle class to allowed-lanes.
AllowedLanesCont myAllowed;
AllowedLanesCont myOrigAllowed;

/// @brief From target edge to lanes allowed to be used to reach it
AllowedLanesByTarget myAllowedTargets;
AllowedLanesByTarget myOrigAllowedTargets;

/// @brief The intersection of lane permissions for this edge
SVCPermissions myMinimumPermissions = SVCAll;
Expand All @@ -933,6 +934,9 @@ class MSEdge : public Named, public Parameterised {
SVCPermissions myOriginalMinimumPermissions = SVCAll;
/// @brief The original union of lane permissions for this edge (before temporary modifications)
SVCPermissions myOriginalCombinedPermissions;

/// @brief whether transient permission changes were applied to this edge or a predecessor
bool myHaveTransientPermissions;
/// @}

/// @brief the other taz-connector if this edge isTazConnector, otherwise nullptr
Expand Down Expand Up @@ -999,6 +1003,7 @@ class MSEdge : public Named, public Parameterised {

/// @brief The successors available for a given vClass
mutable std::map<SUMOVehicleClass, MSConstEdgePairVector> myClassesViaSuccessorMap;
mutable std::map<SUMOVehicleClass, MSConstEdgePairVector> myOrigClassesViaSuccessorMap;

/// @brief The bounding rectangle of end nodes incoming or outgoing edges for taz connectors or of my own start and end node for normal edges
Boundary myBoundary;
Expand Down
1 change: 1 addition & 0 deletions src/microsim/transportables/MSTransportable.cpp
Expand Up @@ -26,6 +26,7 @@
#include <utils/vehicle/SUMOVehicleParameter.h>
#include <utils/router/PedestrianRouter.h>
#include <utils/router/IntermodalRouter.h>
#include <libsumo/TraCIConstants.h>
#include <microsim/MSEdge.h>
#include <microsim/MSLane.h>
#include <microsim/MSNet.h>
Expand Down
2 changes: 1 addition & 1 deletion src/netbuild/NBAlgorithms_Railway.cpp
Expand Up @@ -84,7 +84,7 @@ NBRailwayTopologyAnalyzer::Track::getSuccessors(SUMOVehicleClass svc) const {


const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
NBRailwayTopologyAnalyzer::Track::getViaSuccessors(SUMOVehicleClass svc) const {
NBRailwayTopologyAnalyzer::Track::getViaSuccessors(SUMOVehicleClass svc, bool /*ignoreTransientPermissions*/) const {
if ((minPermissions & svc) != 0) {
return viaSuccessors;
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/netbuild/NBAlgorithms_Railway.h
Expand Up @@ -66,7 +66,7 @@ class NBRailwayTopologyAnalyzer {

void addSuccessor(Track* track);
const std::vector<Track*>& getSuccessors(SUMOVehicleClass svc = SVC_IGNORING) const;
const std::vector<std::pair<const Track*, const Track*> >& getViaSuccessors(SUMOVehicleClass svc = SVC_IGNORING) const;
const std::vector<std::pair<const Track*, const Track*> >& getViaSuccessors(SUMOVehicleClass svc = SVC_IGNORING, bool ignoreTransientPermissions = false) const;

const std::string& getID() const {
return id;
Expand Down
2 changes: 1 addition & 1 deletion src/netbuild/NBEdge.cpp
Expand Up @@ -4692,7 +4692,7 @@ NBEdge::getSuccessors(SUMOVehicleClass vClass) const {


const ConstRouterEdgePairVector&
NBEdge::getViaSuccessors(SUMOVehicleClass vClass) const {
NBEdge::getViaSuccessors(SUMOVehicleClass vClass, bool /*ignoreTransientPermissions*/) const {
// @todo cache successors instead of recomputing them every time
myViaSuccessors.clear();
for (const Connection& con : myConnections) {
Expand Down
7 changes: 4 additions & 3 deletions src/netbuild/NBEdge.h
Expand Up @@ -67,7 +67,7 @@ class NBRouterEdge {
virtual double getLength() const = 0;
virtual const NBRouterEdge* getBidiEdge() const = 0;
virtual int getNumericalID() const = 0;
virtual const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const = 0;
virtual const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const = 0;
virtual bool isInternal() const {
return false;
}
Expand Down Expand Up @@ -327,8 +327,9 @@ class NBEdge : public Named, public Parameterised, public NBRouterEdge {
bool isInternal() const {
return true;
}
const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const {
const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
UNUSED_PARAMETER(vClass);
UNUSED_PARAMETER(ignoreTransientPermissions);
return myViaSuccessors;
}
/// }@
Expand Down Expand Up @@ -1515,7 +1516,7 @@ class NBEdge : public Named, public Parameterised, public NBRouterEdge {

/** @brief Returns the following edges for the given vClass
*/
const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;
const ConstRouterEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;

//@}
const std::string& getID() const {
Expand Down
7 changes: 7 additions & 0 deletions src/netbuild/NBVehicle.h
Expand Up @@ -58,6 +58,13 @@ class NBVehicle {
return myVClass;
}

/** @brief Returns whether this object is ignoring transient permission
* changes (during routing)
*/
bool ignoreTransientPermissions() const {
return false;
};

double getLength() const {
return myLength;
}
Expand Down
2 changes: 1 addition & 1 deletion src/router/ROEdge.cpp
Expand Up @@ -399,7 +399,7 @@ ROEdge::getSuccessors(SUMOVehicleClass vClass) const {


const ROConstEdgePairVector&
ROEdge::getViaSuccessors(SUMOVehicleClass vClass) const {
ROEdge::getViaSuccessors(SUMOVehicleClass vClass, bool /*ignoreTransientPermissions*/) const {
if (vClass == SVC_IGNORING || !RONet::getInstance()->hasPermissions() || isTazConnector()) {
return myFollowingViaEdges;
}
Expand Down
2 changes: 1 addition & 1 deletion src/router/ROEdge.h
Expand Up @@ -350,7 +350,7 @@ class ROEdge : public Named, public Parameterised {
* @param[in] vClass The vClass for which to restrict the successors
* @return The eligible following edges
*/
const ROConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const;
const ROConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const;


/** @brief Returns the number of edges connected to this edge
Expand Down
6 changes: 6 additions & 0 deletions src/router/RORoutable.h
Expand Up @@ -110,6 +110,12 @@ class RORoutable {
return getType() != 0 ? getType()->vehicleClass : SVC_IGNORING;
}

/** @brief Returns whether this object is ignoring transient permission
* changes (during routing)
*/
bool ignoreTransientPermissions() const {
return false;
};

/// @brief Returns the vehicle's maximum speed
inline double getMaxSpeed() const {
Expand Down
12 changes: 7 additions & 5 deletions src/utils/router/CarEdge.h
Expand Up @@ -67,15 +67,16 @@ class CarEdge : public IntermodalEdge<E, L, N, V> {
}
}

virtual const std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> >& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const {
virtual const std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> >& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
if (vClass == SVC_IGNORING) {
return this->myFollowingViaEdges;
}
#ifdef HAVE_FOX
FXMutexLock locker(myLock);
#endif
typename std::map<SUMOVehicleClass, std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> > >::const_iterator i = myClassesViaSuccessorMap.find(vClass);
if (i != myClassesViaSuccessorMap.end()) {
auto& viaMap = ignoreTransientPermissions ? myOrigClassesViaSuccessorMap : myClassesViaSuccessorMap;
typename std::map<SUMOVehicleClass, std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> > >::const_iterator i = viaMap.find(vClass);
if (i != viaMap.end()) {
// can use cached value
return i->second;
} else {
Expand All @@ -86,10 +87,10 @@ class CarEdge : public IntermodalEdge<E, L, N, V> {
}
for (const std::pair<const _IntermodalEdge*, const _IntermodalEdge*>& e : this->myFollowingViaEdges) {
if (!e.first->includeInRoute(false) || e.first->getEdge() == this->getEdge() || classedCarFollowers.count(e.first->getEdge()) > 0) {
myClassesViaSuccessorMap[vClass].push_back(e);
viaMap[vClass].push_back(e);
}
}
return myClassesViaSuccessorMap[vClass];
return viaMap[vClass];
}
}

Expand Down Expand Up @@ -144,6 +145,7 @@ class CarEdge : public IntermodalEdge<E, L, N, V> {

/// @brief The successors available for a given vClass
mutable std::map<SUMOVehicleClass, std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> > > myClassesViaSuccessorMap;
mutable std::map<SUMOVehicleClass, std::vector<std::pair<const _IntermodalEdge*, const _IntermodalEdge*> > > myOrigClassesViaSuccessorMap;

#ifdef HAVE_FOX
/// The mutex used to avoid concurrent updates of myClassesSuccessorMap
Expand Down
3 changes: 2 additions & 1 deletion src/utils/router/DijkstraRouter.h
Expand Up @@ -124,6 +124,7 @@ class DijkstraRouter : public SUMOAbstractRouter<E, V> {
std::cout << "DEBUG: starting search for '" << Named::getIDSecure(vehicle) << "' time: " << STEPS2TIME(msTime) << "\n";
#endif
const SUMOVehicleClass vClass = vehicle == nullptr ? SVC_IGNORING : vehicle->getVClass();
const bool ignoreTransient = vehicle == nullptr ? false : vehicle->ignoreTransientPermissions();
std::tuple<const E*, const V*, SUMOTime> query = std::make_tuple(from, vehicle, msTime);
if ((this->myBulkMode || (this->myAutoBulkMode && query == myLastQuery)) && !this->myAmClean) {
#ifdef DijkstraRouter_DEBUG_BULKMODE
Expand Down Expand Up @@ -203,7 +204,7 @@ class DijkstraRouter : public SUMOAbstractRouter<E, V> {
myExternalEffort->update(minEdge->getNumericalID(), minimumInfo->prev->edge->getNumericalID(), minEdge->getLength());
}
// check all ways from the node with the minimal length
for (const std::pair<const E*, const E*>& follower : minEdge->getViaSuccessors(vClass)) {
for (const std::pair<const E*, const E*>& follower : minEdge->getViaSuccessors(vClass, ignoreTransient)) {
auto& followerInfo = this->myEdgeInfos[follower.first->getNumericalID()];
// check whether it can be used
if (followerInfo.prohibited || this->isProhibited(follower.first, vehicle)) {
Expand Down
3 changes: 2 additions & 1 deletion src/utils/router/IntermodalEdge.h
Expand Up @@ -136,8 +136,9 @@ class IntermodalEdge : public Named {
return myFollowingEdges;
}

virtual const std::vector<std::pair<const IntermodalEdge*, const IntermodalEdge*> >& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const {
virtual const std::vector<std::pair<const IntermodalEdge*, const IntermodalEdge*> >& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
UNUSED_PARAMETER(vClass);
UNUSED_PARAMETER(ignoreTransientPermissions);
// the network is already tailored. No need to check for permissions here
return myFollowingViaEdges;
}
Expand Down
7 changes: 7 additions & 0 deletions src/utils/router/IntermodalTrip.h
Expand Up @@ -62,6 +62,13 @@ class IntermodalTrip {
return vehicle != 0 ? vehicle->getVClass() : SVC_PEDESTRIAN;
}

/** @brief Returns whether this object is ignoring transient permission
* changes (during routing)
*/
bool ignoreTransientPermissions() const {
return vehicle != 0 ? vehicle->ignoreTransientPermissions() : false;
};

inline double getLength() const {
// person length is arbitrary (only used in the context of rail-reversal validity
return vehicle != 0 ? vehicle->getVehicleType().getLength() : 1;
Expand Down
3 changes: 2 additions & 1 deletion src/utils/router/RailEdge.h
Expand Up @@ -233,7 +233,8 @@ class RailEdge {
return myOriginal != nullptr && myOriginal->restricts(vehicle);
}

const ConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING) const {
const ConstEdgePairVector& getViaSuccessors(SUMOVehicleClass vClass = SVC_IGNORING, bool ignoreTransientPermissions = false) const {
UNUSED_PARAMETER(ignoreTransientPermissions); // @todo this should be changed (somewhat hidden by #14756)
if (vClass == SVC_IGNORING || myOriginal == nullptr || myOriginal->isTazConnector()) { // || !MSNet::getInstance()->hasPermissions()) {
return myViaSuccessors;
}
Expand Down

0 comments on commit d42030e

Please sign in to comment.