66template<
class E,
class V>
82 const bool havePermissions =
false,
const bool haveRestrictions =
false,
double maxTrainLength = 5000) :
83 SUMOAbstractRouter<E, V>(
"RailwayRouter", unbuildIsWarning, effortOperation, ttOperation, havePermissions, haveRestrictions),
87 for (
const E*
const edge : edges) {
103 bool compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent =
false) {
106 WRITE_WARNINGF(
"Vehicle '%' with length % exceeds configured value of --railway.max-train-length %",
109 return _compute(from, to, vehicle, msTime, into, silent,
false);
114 std::map<const _RailEdge*, double> railEdges;
115 for (
auto item : toProhibit) {
116 railEdges[item.first->getRailwayRoutingEdge()] = item.second;
120#ifdef RailwayRouter_DEBUG_ROUTES
121 std::cout <<
"RailRouter prohibit=" <<
toString(toProhibit) <<
"\n";
126 double recomputeCosts(
const std::vector<const E*>& edges,
const V*
const v,
SUMOTime msTime,
double* lengthp =
nullptr)
const {
128 const E* prev =
nullptr;
131 for (
const E*
const e : edges) {
132 if (prev !=
nullptr && e->getBidiEdge() == prev) {
133 if (e->getLength() > v->getLength()) {
136 const double savingsFactor = 1 - v->getLength() / e->getLength();
137 double effortCorrection = 0;
138 double lengthCorrection = 0.;
139 effortCorrection += this->
getEffort(prev, v, timeCorrection);
140 this->
updateViaCost(prev, e, v, timeCorrection, effortCorrection, lengthCorrection);
141 effort -= savingsFactor * effortCorrection;
142 if (lengthp !=
nullptr) {
143 *lengthp -= savingsFactor * lengthCorrection;
169 bool _compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent,
bool avoidUnsafeBackTracking) {
171 std::vector<double> backLengths;
172 double backDist = vehicle->getLength() - from->getLength();
173 const E* start = from;
174 while (backDist > 0) {
176 if (prev ==
nullptr) {
177#ifdef RailwayRouter_DEBUG_ROUTES
178 std::cout <<
" Could not determine back edge for vehicle '" << vehicle->getID() <<
"' when routing from edge '" << from->getID() <<
"' at time=" <<
time2string(msTime) <<
"\n";
183 backDist -= prev->getLength();
184 if (avoidUnsafeBackTracking && prev->getSuccessors().size() > 1) {
185 bool foundSwitch =
false;
186 for (
const E* succ : prev->getSuccessors()) {
187 if (succ != start && succ != prev->getBidiEdge()) {
196 backLengths.push_back(prev->getLength() + (backLengths.empty()
197 ?
MIN2(vehicle->getLength(), from->getLength())
198 : backLengths.back()));
202 std::vector<const _RailEdge*> intoTmp;
203 bool success =
myInternalRouter->
compute(start->getRailwayRoutingEdge(), to->getRailwayRoutingEdge(), vehicle, msTime, intoTmp, silent);
204#ifdef RailwayRouter_DEBUG_ROUTES
205 std::cout <<
"RailRouter veh=" << vehicle->getID() <<
" from=" << from->getID() <<
" to=" << to->getID() <<
" t=" <<
time2string(msTime)
206 <<
" safe=" << avoidUnsafeBackTracking <<
" success=" << success <<
" into=" <<
toString(into) <<
"\n";
209 const size_t intoSize = into.size();
210 int backIndex = (int)backLengths.size();
211 for (
const _RailEdge* railEdge : intoTmp) {
212 if (railEdge->getOriginal() !=
nullptr) {
216 const double length = backIndex >= 0 ? backLengths[backIndex] : vehicle->getLength();
217 railEdge->insertOriginalEdges(length, into);
219#ifdef RailwayRouter_DEBUG_ROUTES
220 std::cout <<
"RailRouter: internal result=" <<
toString(intoTmp) <<
"\n";
221 std::cout <<
"RailRouter: expanded result=" <<
toString(into) <<
"\n";
223 if (backLengths.size() > 0) {
225 into.erase(into.begin() + intoSize, into.begin() + intoSize + backLengths.size());
226#ifdef RailwayRouter_DEBUG_ROUTES
227 std::cout <<
"RailRouter: backLengths=" <<
toString(backLengths) <<
" intoSize=" << intoSize <<
" final result=" <<
toString(into) <<
"\n";
229 if (*(into.begin() + intoSize) != from) {
230 if (!avoidUnsafeBackTracking) {
233 into.erase(into.begin() + intoSize, into.end());
234 return _compute(from, to, vehicle, msTime, into, silent,
true);
236 WRITE_WARNING(
"Railway routing failure due to turn-around on short edge '" + from->getID()
237 +
"' for vehicle '" + vehicle->getID() +
"' time=" +
time2string(msTime) +
".");
243 for (
const E* e : into) {
261 FXMutexLock locker(myLock);
280 std::vector<const E*> repl;
282 assert(repl.size() > 0);
286 for (
const E* e : repl) {
287 result += (*myStaticOperation)(e, veh, time + result);
288 seenDist += e->getLength();
290 const double lengthOnLastEdge =
MAX2(0.0, veh->getLength() - seenDist);
305 const E* result =
nullptr;
306#ifdef RailwayRouter_DEBUG_ROUTES
307 std::cout <<
" getStraightPredecessor edge=" << edge->getID() <<
" prevRouteSize=" << prevRoute.size() <<
" backIndex=" << backIndex <<
"\n";
309 if ((
int)prevRoute.size() > backIndex) {
310 return prevRoute[(int)prevRoute.size() - 1 - backIndex];
312 for (
const E* cand : edge->getPredecessors()) {
313 if (!cand->isInternal() && cand->getBidiEdge() != edge) {
315 if (result ==
nullptr) {
341 mutable FXMutex myLock;
356template<
class E,
class V>
358template<
class E,
class V>
360template<
class E,
class V>
#define WRITE_WARNINGF(...)
#define WRITE_WARNING(msg)
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Computes the shortest path through a network using the Dijkstra algorithm.
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
the edge type representing backward edges
void insertOriginalEdges(double length, std::vector< const E * > &into) const
const E * getOriginal() const
Returns the original edge.
SUMOAbstractRouter< _RailEdge, V > _InternalRouter
static double myReversalPenaltyFactor
RailwayRouter< E, V > *const myOriginal
RailwayRouter(RailwayRouter *other)
DijkstraRouter< _RailEdge, V > _InternalDijkstra
std::vector< _RailEdge * > myInitialEdges
a RailEdge for every existing edge, filled on construction (but not in clones)
RailwayRouter & operator=(const RailwayRouter &s)
Invalidated assignment operator.
std::vector< _RailEdge * > myRailEdges
complete rail network filled on demand (but not in clones)
void prohibit(const Prohibitions &toProhibit)
double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
const bool mySilent
whether to suppress warning/error if no route was found
bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum effort at the given time The definition of...
RailwayRouter(const std::vector< E * > &edges, bool unbuildIsWarning, typename SUMOAbstractRouter< E, V >::Operation effortOperation, typename SUMOAbstractRouter< E, V >::Operation ttOperation=nullptr, bool silent=false, const bool havePermissions=false, const bool haveRestrictions=false, double maxTrainLength=5000)
Constructor.
_InternalRouter * myInternalRouter
static SUMOAbstractRouter< E, V >::Operation myStaticOperation
The object's operation to perform. (hack)
const double myMaxTrainLength
bool _compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent, bool avoidUnsafeBackTracking)
void ensureInternalRouter()
const std::vector< _RailEdge * > & getRailEdges()
RailEdge< E, V > _RailEdge
static double myReversalPenalty
static const E * getStraightPredecessor(const E *edge, std::vector< const E * > &prevRoute, int backIndex)
static double getTravelTimeStatic(const RailEdge< E, V > *const edge, const V *const veh, double time)
std::map< const E *, double > Prohibitions
SUMOAbstractRouter< E, V > * clone()
virtual ~RailwayRouter()
Destructor.
MsgHandler *const myErrorMsgHandler
the handler for routing errors
const bool myHavePermissions
whether edge permissions need to be considered
void updateViaCost(const E *const prev, const E *const e, const V *const v, double &time, double &effort, double &length) const
double getEffort(const E *const e, const V *const v, double t) const
virtual void prohibit(const Prohibitions &toProhibit)
Prohibitions myProhibited
The list of explicitly prohibited edges and estimated end time of prohibition.
const bool myHaveRestrictions
whether edge restrictions need to be considered
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const