66template<
class E,
class V>
82 bool havePermissions =
false,
const bool haveRestrictions =
false,
double maxTrainLength = 5000,
83 double reversalPenalty = 60) :
84 SUMOAbstractRouter<E, V>(
"RailwayRouter", unbuildIsWarning, effortOperation, ttOperation, havePermissions, haveRestrictions),
91 for (
const E*
const edge : edges) {
107 bool compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent =
false) {
110 WRITE_WARNINGF(
"Vehicle '%' with length % exceeds configured value of --railway.max-train-length %",
113 return _compute(from, to, vehicle, msTime, into, silent,
false);
118 std::map<const _RailEdge*, double> railEdges;
119 for (
auto item : toProhibit) {
120 railEdges[item.first->getRailwayRoutingEdge()] = item.second;
124#ifdef RailwayRouter_DEBUG_ROUTES
125 std::cout <<
"RailRouter numProhibitions=" << toProhibit.size() <<
"\n";
130 double recomputeCosts(
const std::vector<const E*>& edges,
const V*
const v,
SUMOTime msTime,
double* lengthp =
nullptr)
const {
132 const E* prev =
nullptr;
135 for (
const E*
const e : edges) {
136 if (prev !=
nullptr && e->getBidiEdge() == prev) {
137 if (e->getLength() > v->getLength()) {
140 const double savingsFactor = 1 - v->getLength() / e->getLength();
141 double effortCorrection = 0;
142 double lengthCorrection = 0.;
143 effortCorrection += this->
getEffort(prev, v, timeCorrection);
144 this->
updateViaCost(prev, e, v, timeCorrection, effortCorrection, lengthCorrection);
145 effort -= savingsFactor * effortCorrection;
146 if (lengthp !=
nullptr) {
147 *lengthp -= savingsFactor * lengthCorrection;
179 bool _compute(
const E* from,
const E* to,
const V*
const vehicle,
SUMOTime msTime, std::vector<const E*>& into,
bool silent,
bool avoidUnsafeBackTracking) {
182 std::vector<double> backLengths;
183 double backDist =
myReversalPenalty >= 0 ? vehicle->getLength() - from->getLength() : 0;
184 const E* start = from;
185 while (backDist > 0) {
187 if (prev ==
nullptr) {
188#ifdef RailwayRouter_DEBUG_ROUTES
189 std::cout <<
" Could not determine back edge for vehicle '" << vehicle->getID() <<
"' when routing from edge '" << from->getID() <<
"' at time=" <<
time2string(msTime) <<
"\n";
194 backDist -= prev->getLength();
195 if (avoidUnsafeBackTracking && prev->getSuccessors().size() > 1) {
196 bool foundSwitch =
false;
197 for (
const E* succ : prev->getSuccessors()) {
198 if (succ != start && succ != prev->getBidiEdge()) {
207 backLengths.push_back(prev->getLength() + (backLengths.empty()
208 ?
MIN2(vehicle->getLength(), from->getLength())
209 : backLengths.back()));
213 std::vector<const _RailEdge*> intoTmp;
217 bool success =
myInternalRouter->compute(start->getRailwayRoutingEdge(), to->getRailwayRoutingEdge(), vehicle, msTime, intoTmp, silent);
219#ifdef RailwayRouter_DEBUG_ROUTES
220 std::cout <<
"RailRouter veh=" << vehicle->getID() <<
" from=" << from->getID() <<
" to=" << to->getID() <<
" t=" <<
time2string(msTime)
221 <<
" safe=" << avoidUnsafeBackTracking <<
" success=" << success <<
" into=" <<
toString(into) <<
"\n";
224 const size_t intoSize = into.size();
225 int backIndex = (int)backLengths.size();
226 for (
const _RailEdge* railEdge : intoTmp) {
227 if (railEdge->getOriginal() !=
nullptr) {
231 const double length = backIndex >= 0 ? backLengths[backIndex] : vehicle->getLength();
232 railEdge->insertOriginalEdges(length, into);
234#ifdef RailwayRouter_DEBUG_ROUTES
235 std::cout <<
"RailRouter: internal result=" <<
toString(intoTmp) <<
"\n";
236 std::cout <<
"RailRouter: expanded result=" <<
toString(into) <<
"\n";
237 std::cout <<
"RailRouter: backLengths=" <<
toString(backLengths) <<
" bls=" << backLengths.size() <<
" intoSize=" << intoSize <<
" final result=" <<
toString(into) <<
"\n";
239 if (backLengths.size() > 0) {
241 into.erase(into.begin() + intoSize, into.begin() + intoSize + backLengths.size());
242 if (*(into.begin() + intoSize) != from) {
243 if (!avoidUnsafeBackTracking) {
246 into.erase(into.begin() + intoSize, into.end());
248 success =
_compute(from, to, vehicle, msTime, into, silent,
true);
251 WRITE_WARNING(
"Railway routing failure due to turn-around on short edge '" + from->getID()
252 +
"' for vehicle '" + vehicle->getID() +
"' time=" +
time2string(msTime) +
".");
258 for (
const E* e : into) {
259 if (this->
myProhibited.find(e) != this->myProhibited.end()) {
276 FXMutexLock locker(
myLock);
295 std::vector<const E*> repl;
297 assert(repl.size() > 0);
301 for (
const E* e : repl) {
302 result += (*myStaticOperation)(e, veh, time + result);
303 seenDist += e->getLength();
305 const double lengthOnLastEdge =
MAX2(0.0, veh->getLength() - seenDist);
320 const E* result =
nullptr;
321#ifdef RailwayRouter_DEBUG_ROUTES
322 std::cout <<
" getStraightPredecessor edge=" << edge->getID() <<
" prevRouteSize=" << prevRoute.size() <<
" backIndex=" << backIndex <<
"\n";
324 if ((
int)prevRoute.size() > backIndex) {
325 return prevRoute[(int)prevRoute.size() - 1 - backIndex];
327 for (
const E* cand : edge->getPredecessors()) {
328 if (!cand->isInternal() && cand->getBidiEdge() != edge) {
330 if (result ==
nullptr) {
374template<
class E,
class V>
376template<
class E,
class V>
378template<
class E,
class V>
template FXMutex GLObjectValuePassConnector< double >::myLock
#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)
void setBulkMode(const bool mode)
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...
_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()
const E * myLastFrom
track previous edge for correct bulk routing
virtual ~RailwayRouter()
Destructor.
RailwayRouter(const std::vector< E * > &edges, bool unbuildIsWarning, typename SUMOAbstractRouter< E, V >::Operation effortOperation, typename SUMOAbstractRouter< E, V >::Operation ttOperation=nullptr, bool silent=false, bool havePermissions=false, const bool haveRestrictions=false, double maxTrainLength=5000, double reversalPenalty=60)
Constructor.
MsgHandler *const myErrorMsgHandler
the handler for routing errors
const bool myHavePermissions
whether edge permissions need to be considered
double(* Operation)(const E *const, const V *const, double)
Type of the function that is used to retrieve the edge effort.
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
SUMOAbstractRouter(const std::string &type, bool unbuildIsWarning, Operation operation, Operation ttOperation, const bool havePermissions, const bool haveRestrictions)
Constructor.
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 double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const