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 virtual 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
427 virtual bool supportsProhibitions() const {
428 return true;
429 }
430
432 void buildPathFrom(const typename SUMOAbstractRouter<E, V>::EdgeInfo* rbegin, std::vector<const E*>& edges) {
433 std::vector<const E*> tmp;
434 while (rbegin != nullptr) {
435 tmp.push_back(rbegin->edge);
436 rbegin = rbegin->prev;
437 }
438 std::copy(tmp.rbegin(), tmp.rend(), std::back_inserter(edges));
439 }
440
441protected:
444
447
450
453
456
459
462
465
468
470 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo> myEdgeInfos;
471
473 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFrontierList;
475 std::vector<typename SUMOAbstractRouter<E, V>::EdgeInfo*> myFound;
476
477private:
479 const std::string myType;
480
482 long long int myQueryVisits;
483 long long int myNumQueries;
485 long long int myQueryStartTime;
486 long long int myQueryTimeSum;
487
488private:
491};
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:58
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:49
double prohibitionBegin
the time at which a temporary prohibition 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 prohibition ends
SVCPermissions prohibitedPermissions
temporary permission change
Operation myTTOperation
long long int myNumQueries
const bool myHavePermissions
long long int myQueryVisits
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
virtual void setBulkMode(const bool mode)
SUMOAbstractRouter & operator=(const SUMOAbstractRouter &s)=delete
Invalidated assignment operator.
std::map< const MSEdge *, RouterProhibition > Prohibitions
std::vector< typename SUMOAbstractRouter< MSEdge, SUMOVehicle >::EdgeInfo > myEdgeInfos
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 MSEdge *const, const SUMOVehicle *const, double)
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
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)
virtual bool supportsProhibitions() const
const bool myHaveRestrictions
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.
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
virtual void setMsgHandler(MsgHandler *const errorMsgHandler)
void endQuery(int visits)
virtual ~SUMOAbstractRouter()
Destructor.
MsgHandler * myErrorMsgHandler
std::vector< typename SUMOAbstractRouter< MSEdge, SUMOVehicle >::EdgeInfo * > myFrontierList
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< MSEdge, SUMOVehicle >::EdgeInfo * > myFound
const std::string myType
static long getCurrentMillis()
Returns the current time in milliseconds.
Definition SysUtils.cpp:45
#define UNUSED_PARAMETER(x)
Definition json.hpp:4471
Prohibitions and their estimated end time.
SVCPermissions permissions