Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
SUMOAbstractRouter.h
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2006-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
20// An abstract router base class
21/****************************************************************************/
22#pragma once
23#include <config.h>
24
25#include <string>
26#include <vector>
27#include <algorithm>
28#include <iterator>
29#include <assert.h>
34
35//#define ROUTER_DEBUG_HINT
36//#define ROUTER_DEBUG_COND (true)
37
38
39// ===========================================================================
40// class definitions
41// ===========================================================================
42
45 double begin = 0;
46 double end = std::numeric_limits<double>::max();
48};
49
54template<class E, class V>
56public:
62 class EdgeInfo {
63 public:
65 EdgeInfo(const E* const e)
66 : edge(e), effort(std::numeric_limits<double>::max()),
67 heuristicEffort(std::numeric_limits<double>::max()),
69
71 const E* const edge;
72
74 double effort;
75
77 // only used by A*
79
81 double leaveTime;
82
84 const EdgeInfo* prev;
85
87 bool visited;
88
91
94
97
98 inline void reset() {
99 effort = std::numeric_limits<double>::max();
100 heuristicEffort = std::numeric_limits<double>::max();
101 visited = false;
102 }
103
104 };
105
107 typedef double(* Operation)(const E* const, const V* const, double);
108
109 typedef std::map<const E*, RouterProhibition> Prohibitions;
110
112 SUMOAbstractRouter(const std::string& type, bool unbuildIsWarning, Operation operation, Operation ttOperation,
113 const bool havePermissions, const bool haveRestrictions) :
114 myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
115 myOperation(operation), myTTOperation(ttOperation),
116 myBulkMode(false),
117 myAutoBulkMode(false),
118 myAmClean(true),
119 myHavePermissions(havePermissions),
120 myHaveRestrictions(haveRestrictions),
121 myType(type),
122 myQueryVisits(0),
123 myNumQueries(0),
125 myQueryTimeSum(0) {
126 }
127
142
143
144
147 if (myNumQueries > 0) {
148 WRITE_MESSAGE(myType + " answered " + toString(myNumQueries) + " queries and explored " + toString((double)myQueryVisits / (double)myNumQueries) + " edges on average.");
149 WRITE_MESSAGE(myType + " spent " + elapsedMs2string(myQueryTimeSum) + " answering queries (" + toString((double)myQueryTimeSum / (double)myNumQueries) + "ms on average).");
150 }
151 }
152
153 virtual SUMOAbstractRouter* clone() = 0;
154
155 inline void init(const int edgeID, const SUMOTime msTime) {
156// if (!myAmClean) {
157 // all EdgeInfos touched in the previous query are either in myFrontierList or myFound: clean those up
158 for (auto& edgeInfo : myFrontierList) {
159 edgeInfo->reset();
160 }
161 myFrontierList.clear();
162 for (auto& edgeInfo : myFound) {
163 edgeInfo->reset();
164 }
165 myFound.clear();
166 if (edgeID > -1) {
167 // add begin node
168 auto& fromInfo = myEdgeInfos[edgeID];
169 fromInfo.effort = 0.;
170 fromInfo.heuristicEffort = 0.;
171 fromInfo.prev = nullptr;
172 fromInfo.leaveTime = STEPS2TIME(msTime);
173 myFrontierList.push_back(&fromInfo);
174 }
175 myAmClean = true;
176// }
177 }
178
180 virtual void reset(const V* const vehicle) {
181 UNUSED_PARAMETER(vehicle);
182 }
183
184 void setMsgHandler(MsgHandler* const errorMsgHandler) {
185 myErrorMsgHandler = errorMsgHandler;
186 }
187
188 const std::string& getType() const {
189 return myType;
190 }
191
192 inline const typename SUMOAbstractRouter<E, V>::EdgeInfo& getEdgeInfo(int index) const {
193 return myEdgeInfos[index];
194 }
195
198 virtual bool compute(const E* from, const E* to, const V* const vehicle,
199 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) = 0;
200
201
206 inline bool compute(
207 const E* from, double fromPos,
208 const E* to, double toPos,
209 const V* const vehicle,
210 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
211 if (from != to || fromPos <= toPos) {
212 return compute(from, to, vehicle, msTime, into, silent);
213 } else {
214 return computeLooped(from, to, vehicle, msTime, into, silent);
215 }
216 }
217
218
221 inline bool computeLooped(const E* from, const E* to, const V* const vehicle,
222 SUMOTime msTime, std::vector<const E*>& into, bool silent = false) {
223 if (from != to) {
224 return compute(from, to, vehicle, msTime, into, silent);
225 }
226 double minEffort = std::numeric_limits<double>::max();
227 std::vector<const E*> best;
228 const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
229 for (const std::pair<const E*, const E*>& follower : from->getViaSuccessors(vClass)) {
230 std::vector<const E*> tmp;
231 compute(follower.first, to, vehicle, msTime, tmp, true);
232 if (tmp.size() > 0) {
233 double effort = recomputeCosts(tmp, vehicle, msTime);
234 if (effort < minEffort) {
235 minEffort = effort;
236 best = tmp;
237 }
238 }
239 }
240 if (minEffort != std::numeric_limits<double>::max()) {
241 into.push_back(from);
242 std::copy(best.begin(), best.end(), std::back_inserter(into));
243 return true;
244 } else if (!silent && myErrorMsgHandler != nullptr) {
245 myErrorMsgHandler->informf(TL("No connection between edge '%' and edge '%' found."), from->getID(), to->getID());
246 }
247 return false;
248 }
249
250 inline bool isProhibited(const E* const edge, const V* const vehicle, double t) const {
251 return (myProhibited.size() > 0
252 && (myEdgeInfos[edge->getNumericalID()].prohibitedPermissions & vehicle->getVClass()) != vehicle->getVClass()
253 && myEdgeInfos[edge->getNumericalID()].prohibitionBegin <= t
254 && myEdgeInfos[edge->getNumericalID()].prohibitionEnd == std::numeric_limits<double>::max())
255 || (myHavePermissions && edge->prohibits(vehicle)) || (myHaveRestrictions && edge->restricts(vehicle));
256 }
257
258 inline double getTravelTime(const E* const e, const V* const v, const double t, const double effort) const {
259 return myTTOperation == nullptr ? effort : (*myTTOperation)(e, v, t);
260 }
261
262 inline void updateViaEdgeCost(const E* viaEdge, const V* const v, double& time, double& effort, double& length) const {
263 while (viaEdge != nullptr && viaEdge->isInternal()) {
264 const double viaEffortDelta = this->getEffort(viaEdge, v, time);
265 time += getTravelTime(viaEdge, v, time, viaEffortDelta);
266 effort += viaEffortDelta;
267 length += viaEdge->getLength();
268 viaEdge = viaEdge->getViaSuccessors().front().second;
269 }
270 }
271
272 inline void updateViaCost(const E* const prev, const E* const e, const V* const v, double& time, double& effort, double& length) const {
273 if (prev != nullptr) {
274 for (const std::pair<const E*, const E*>& follower : prev->getViaSuccessors()) {
275 if (follower.first == e) {
276 updateViaEdgeCost(follower.second, v, time, effort, length);
277 break;
278 }
279 }
280 }
281 const double effortDelta = this->getEffort(e, v, time);
282 effort += effortDelta;
283 time += getTravelTime(e, v, time, effortDelta);
284 length += e->getLength();
285 }
286
287 bool isValid(const std::vector<const E*>& edges, const V* const v, double t) const {
288 for (const E* const e : edges) {
289 if (isProhibited(e, v, t)) {
290 return false;
291 }
292 }
293 return true;
294 }
295
296 virtual double recomputeCosts(const std::vector<const E*>& edges, const V* const v, SUMOTime msTime, double* lengthp = nullptr) const {
297 double time = STEPS2TIME(msTime);
298 double effort = 0.;
299 double length = 0.;
300 if (lengthp == nullptr) {
301 lengthp = &length;
302 } else {
303 *lengthp = 0.;
304 }
305 const E* prev = nullptr;
306 for (const E* const e : edges) {
307 updateViaCost(prev, e, v, time, effort, *lengthp);
308 prev = e;
309 }
310 return effort;
311 }
312
313
314 inline double recomputeCostsPos(const std::vector<const E*>& edges, const V* const v, double fromPos, double toPos, SUMOTime msTime, double* lengthp = nullptr) const {
315 double effort = recomputeCosts(edges, v, msTime, lengthp);
316 if (!edges.empty()) {
317 const E* first = edges.front();
318 if (first->getLength() == 0) {
319 if (edges.size() > 1 && edges[1]->getLength() > 0) {
320 first = edges[1];
321 } else {
322 return effort;
323 }
324 }
325 const E* last = edges.back();
326 if (last->getLength() == 0) {
327 if (edges.size() > 1 && edges[edges.size() - 2]->getLength() > 0) {
328 last = edges[edges.size() - 2];
329 } else {
330 return effort;
331 }
332 }
333 assert(first->getLength() > 0);
334 assert(last->getLength() > 0);
335 double firstEffort = this->getEffort(first, v, STEPS2TIME(msTime));
336 double lastEffort = this->getEffort(last, v, STEPS2TIME(msTime));
337 effort -= firstEffort * fromPos / first->getLength();
338 effort -= lastEffort * (last->getLength() - toPos) / last->getLength();
339 if (lengthp != nullptr) {
340 (*lengthp) -= fromPos + last->getLength() - toPos;
341 }
342 }
343 return effort;
344 }
345
346
347 inline double setHint(const typename std::vector<const E*>::const_iterator routeBegin, const typename std::vector<const E*>::const_iterator routeEnd, const V* const v, SUMOTime msTime) {
348 double time = STEPS2TIME(msTime);
349 double effort = 0.;
350 double length = 0.;
351 const EdgeInfo* prev = &myEdgeInfos[(*routeBegin)->getNumericalID()];
352 init((*routeBegin)->getNumericalID(), msTime);
353 for (auto e = routeBegin + 1; e != routeEnd; ++e) {
354 if (isProhibited(*e, v)) {
355 return -1;
356 }
357 auto& edgeInfo = myEdgeInfos[(*e)->getNumericalID()];
358 edgeInfo.heuristicEffort = effort;
359 edgeInfo.prev = prev;
360 updateViaCost(prev->edge, *e, v, time, effort, length);
361 edgeInfo.effort = effort;
362 edgeInfo.leaveTime = time;
363 myFound.push_back(&edgeInfo);
364 prev = &edgeInfo;
365#ifdef ROUTER_DEBUG_HINT
366 if (ROUTER_DEBUG_COND) {
367 std::cout << "DEBUG: hit=" << (*e)->getID()
368 << " TT=" << edgeInfo.effort
369 << " EF=" << this->getEffort(*e, v, edgeInfo.leaveTime)
370 << " HT=" << edgeInfo.heuristicEffort << "\n";
371 }
372#endif
373 }
374 return effort;
375 }
376
377
378 inline double getEffort(const E* const e, const V* const v, double t) const {
379 if (this->myProhibited.size() > 0 && myEdgeInfos.size() > 0
380 && myEdgeInfos[e->getNumericalID()].prohibitionEnd > t
381 && myEdgeInfos[e->getNumericalID()].prohibitionBegin <= t
382 && (myEdgeInfos[e->getNumericalID()].prohibitedPermissions & v->getVClass()) != v->getVClass()) {
383 // pass edge after prohibition ends
384 return (myEdgeInfos[e->getNumericalID()].prohibitionEnd - t) + (*myOperation)(e, v, myEdgeInfos[e->getNumericalID()].prohibitionEnd);
385 } else {
386 return (*myOperation)(e, v, t);
387 }
388 }
389
394
395 inline void endQuery(int visits) {
396 myQueryVisits += visits;
398 }
399
400 virtual void setBulkMode(const bool mode) {
401 myBulkMode = mode;
402 }
403
404 inline void setAutoBulkMode(const bool mode) {
405 myAutoBulkMode = mode;
406 }
407
408 virtual void prohibit(const Prohibitions& toProhibit) {
409 for (auto item : this->myProhibited) {
410 myEdgeInfos[item.first->getNumericalID()].prohibitedPermissions = SVCAll;
411 myEdgeInfos[item.first->getNumericalID()].prohibitionBegin = -1;
412 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = -1;
413 }
414 for (auto item : toProhibit) {
415 myEdgeInfos[item.first->getNumericalID()].prohibitionBegin = item.second.begin;
416 myEdgeInfos[item.first->getNumericalID()].prohibitionEnd = item.second.end;
417 myEdgeInfos[item.first->getNumericalID()].prohibitedPermissions = item.second.permissions;
418 //std::cout << item.first->getID() << " " << item.second.begin << " " << item.second.end << " (" << getVehicleClassNames(item.second.permissions) << "\n";
419 }
420 this->myProhibited = toProhibit;
421 }
422
423 bool hasProhibitions() const {
424 return this->myProhibited.size() > 0;
425 }
426
428 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
429 std::vector<const E*> tmp;
430 while (rbegin != nullptr) {
431 tmp.push_back(rbegin->edge);
432 rbegin = rbegin->prev;
433 }
434 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
435 }
436
437protected:
440
443
446
449
452
455
458
461
464
466 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
467
469 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
471 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
472
473private:
475 const std::string myType;
476
478 long long int myQueryVisits;
479 long long int myNumQueries;
481 long long int myQueryStartTime;
482 long long int myQueryTimeSum;
483
484private:
487};
long long int SUMOTime
Definition GUI.h:36
#define WRITE_MESSAGE(msg)
Definition MsgHandler.h:288
#define TL(string)
Definition MsgHandler.h:304
std::string elapsedMs2string(long long int t)
convert ms to string for log output
Definition SUMOTime.cpp:145
#define STEPS2TIME(x)
Definition SUMOTime.h:55
const SVCPermissions SVCAll
all VClasses are allowed
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
void informf(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
Definition MsgHandler.h:116
double prohibitionBegin
the time at which a temporary prohibitione begins
bool visited
whether the edge was already evaluated
EdgeInfo(const E *const e)
Constructor.
const E *const edge
The current edge.
double leaveTime
The time the vehicle leaves the edge.
double effort
Effort to reach the edge.
const EdgeInfo * prev
The previous edge.
double heuristicEffort
Estimated effort to reach the edge (effort + lower bound on remaining effort)
double prohibitionEnd
the time at which a temporary prohibitione ends
SVCPermissions prohibitedPermissions
temporary permission change
Operation myTTOperation
The object's operation to perform for travel times.
void setMsgHandler(MsgHandler *const errorMsgHandler)
const bool myHavePermissions
whether edge permissions need to be considered
bool myBulkMode
whether we are currently operating several route queries in a bulk
long long int myQueryVisits
counters for performance logging
bool computeLooped(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 if from == to,...
virtual SUMOAbstractRouter * clone()=0
long long int myQueryStartTime
the time spent querying in milliseconds
virtual void setBulkMode(const bool mode)
SUMOAbstractRouter & operator=(const SUMOAbstractRouter &s)=delete
Invalidated assignment operator.
std::map< const E *, RouterProhibition > Prohibitions
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo > myEdgeInfos
The container of edge information.
bool compute(const E *from, double fromPos, const E *to, double toPos, 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,...
SUMOAbstractRouter(SUMOAbstractRouter *other)
Copy Constructor.
double(* Operation)(const E *const, const V *const, double)
Type of the function that is used to retrieve the edge effort.
Operation myOperation
The object's operation to perform.
double getTravelTime(const E *const e, const V *const v, const double t, const double effort) const
long long int myQueryTimeSum
void updateViaCost(const E *const prev, const E *const e, const V *const v, double &time, double &effort, double &length) const
virtual void reset(const V *const vehicle)
reset internal caches, used by CHRouter
const std::string & getType() const
double getEffort(const E *const e, const V *const v, double t) const
bool isProhibited(const E *const edge, const V *const vehicle, double t) const
SUMOAbstractRouter(const std::string &type, bool unbuildIsWarning, Operation operation, Operation ttOperation, const bool havePermissions, const bool haveRestrictions)
Constructor.
virtual void prohibit(const Prohibitions &toProhibit)
Prohibitions myProhibited
The list of explicitly prohibited edges and estimated end time of prohibition.
void updateViaEdgeCost(const E *viaEdge, const V *const v, double &time, double &effort, double &length) const
double setHint(const typename std::vector< const E * >::const_iterator routeBegin, const typename std::vector< const E * >::const_iterator routeEnd, const V *const v, SUMOTime msTime)
void init(const int edgeID, const SUMOTime msTime)
void setAutoBulkMode(const bool mode)
bool myAmClean
whether we are already initialized
const bool myHaveRestrictions
whether edge restrictions need to be considered
const SUMOAbstractRouter< E, V >::EdgeInfo & getEdgeInfo(int index) const
void buildPathFrom(const typename SUMOAbstractRouter< E, V >::EdgeInfo *rbegin, std::vector< const E * > &edges)
Builds the path from marked edges.
bool myAutoBulkMode
whether we are currently trying to detect bulk mode automatically
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...
bool isValid(const std::vector< const E * > &edges, const V *const v, double t) const
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime, double *lengthp=nullptr) const
void endQuery(int visits)
virtual ~SUMOAbstractRouter()
Destructor.
MsgHandler * myErrorMsgHandler
the handler for routing errors
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo * > myFrontierList
A container for reusage of the min edge heap.
double recomputeCostsPos(const std::vector< const E * > &edges, const V *const v, double fromPos, double toPos, SUMOTime msTime, double *lengthp=nullptr) const
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo * > myFound
list of visited Edges (for resetting)
const std::string myType
the type of this router
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:44
#define UNUSED_PARAMETER(x)
Definition json.hpp:4471
Prohibitions and their estimated end time.
SVCPermissions permissions