66template<
class E,
class V>
81 const bool havePermissions =
false,
const bool haveRestrictions =
false,
double maxTrainLength = 5000) :
82 SUMOAbstractRouter<E, V>(
"RailwayRouter", unbuildIsWarning, effortOperation, ttOperation, havePermissions, haveRestrictions),
86 for (
const E*
const edge : edges) {
102 bool compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent =
false) {
105 WRITE_WARNINGF(
"Vehicle '%' with length % exceeds configured value of --railway.max-train-length %",
108 return _compute(from, to, vehicle, msTime, into, silent,
false);
113 std::vector<_RailEdge*> railEdges;
114 for (E* edge : toProhibit) {
115 railEdges.push_back(edge->getRailwayRoutingEdge());
119#ifdef RailwayRouter_DEBUG_ROUTES
120 std::cout <<
"RailRouter prohibit=" <<
toString(toProhibit) <<
"\n";
125 double recomputeCosts(
const std::vector<const E*>& edges,
const V*
const v,
SUMOTime msTime,
double* lengthp =
nullptr)
const {
127 const E* prev =
nullptr;
130 for (
const E*
const e : edges) {
131 if (prev !=
nullptr && e->getBidiEdge() == prev) {
132 if (e->getLength() > v->getLength()) {
135 const double savingsFactor = 1 - v->getLength() / e->getLength();
136 double effortCorrection = 0;
137 double lengthCorrection = 0.;
138 effortCorrection += this->
getEffort(prev, v, timeCorrection);
139 this->
updateViaCost(prev, e, v, timeCorrection, effortCorrection, lengthCorrection);
140 effort -= savingsFactor * effortCorrection;
141 if (lengthp !=
nullptr) {
142 *lengthp -= savingsFactor * lengthCorrection;
168 bool _compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent,
bool avoidUnsafeBackTracking) {
170 std::vector<double> backLengths;
171 double backDist = vehicle->getLength() - from->getLength();
172 const E* start = from;
173 while (backDist > 0) {
175 if (prev ==
nullptr) {
176#ifdef RailwayRouter_DEBUG_ROUTES
177 std::cout <<
" Could not determine back edge for vehicle '" << vehicle->getID() <<
"' when routing from edge '" << from->getID() <<
"' at time=" <<
time2string(msTime) <<
"\n";
182 backDist -= prev->getLength();
183 if (avoidUnsafeBackTracking && prev->getSuccessors().size() > 1) {
184 bool foundSwitch =
false;
185 for (
const E* succ : prev->getSuccessors()) {
186 if (succ != start && succ != prev->getBidiEdge()) {
195 backLengths.push_back(prev->getLength() + (backLengths.empty()
196 ?
MIN2(vehicle->getLength(), from->getLength())
197 : backLengths.back()));
201 std::vector<const _RailEdge*> intoTmp;
202 bool success =
myInternalRouter->
compute(start->getRailwayRoutingEdge(), to->getRailwayRoutingEdge(), vehicle, msTime, intoTmp, silent);
203#ifdef RailwayRouter_DEBUG_ROUTES
204 std::cout <<
"RailRouter veh=" << vehicle->getID() <<
" from=" << from->getID() <<
" to=" << to->getID() <<
" t=" <<
time2string(msTime)
205 <<
" safe=" << avoidUnsafeBackTracking <<
" success=" << success <<
" into=" <<
toString(into) <<
"\n";
208 const size_t intoSize = into.size();
209 int backIndex = (int)backLengths.size();
210 for (
const _RailEdge* railEdge : intoTmp) {
211 if (railEdge->getOriginal() !=
nullptr) {
215 const double length = backIndex >= 0 ? backLengths[backIndex] : vehicle->getLength();
216 railEdge->insertOriginalEdges(length, into);
218#ifdef RailwayRouter_DEBUG_ROUTES
219 std::cout <<
"RailRouter: internal result=" <<
toString(intoTmp) <<
"\n";
220 std::cout <<
"RailRouter: expanded result=" <<
toString(into) <<
"\n";
222 if (backLengths.size() > 0) {
224 into.erase(into.begin() + intoSize, into.begin() + intoSize + backLengths.size());
225#ifdef RailwayRouter_DEBUG_ROUTES
226 std::cout <<
"RailRouter: backLengths=" <<
toString(backLengths) <<
" intoSize=" << intoSize <<
" final result=" <<
toString(into) <<
"\n";
228 if (*(into.begin() + intoSize) != from) {
229 if (!avoidUnsafeBackTracking) {
232 into.erase(into.begin() + intoSize, into.end());
233 return _compute(from, to, vehicle, msTime, into, silent,
true);
235 WRITE_WARNING(
"Railway routing failure due to turn-around on short edge '" + from->getID()
236 +
"' for vehicle '" + vehicle->getID() +
"' time=" +
time2string(msTime) +
".");
242 for (
const E* e : into) {
260 FXMutexLock locker(myLock);
279 std::vector<const E*> repl;
281 assert(repl.size() > 0);
285 for (
const E* e : repl) {
286 result += (*myStaticOperation)(e, veh, time + result);
287 seenDist += e->getLength();
289 const double lengthOnLastEdge =
MAX2(0.0, veh->getLength() - seenDist);
304 const E* result =
nullptr;
305#ifdef RailwayRouter_DEBUG_ROUTES
306 std::cout <<
" getStraightPredecessor edge=" << edge->getID() <<
" prevRouteSize=" << prevRoute.size() <<
" backIndex=" << backIndex <<
"\n";
308 if ((
int)prevRoute.size() > backIndex) {
309 return prevRoute[(int)prevRoute.size() - 1 - backIndex];
311 for (
const E* cand : edge->getPredecessors()) {
312 if (!cand->isInternal() && cand->getBidiEdge() != edge) {
314 if (result ==
nullptr) {
340 mutable FXMutex myLock;
355template<
class E,
class V>
357template<
class E,
class V>
359template<
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)
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)
SUMOAbstractRouter< E, V > * clone()
virtual ~RailwayRouter()
Destructor.
void prohibit(const std::vector< E * > &toProhibit)
MsgHandler *const myErrorMsgHandler
the handler for routing errors
std::vector< E * > myProhibited
The list of explicitly prohibited edges.
const bool myHavePermissions
whether edge permissions need to be considered
virtual void prohibit(const std::vector< E * > &toProhibit)
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
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