1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2007-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSRoutingEngine.h
11 /// @author  Michael Behrisch
12 /// @author  Daniel Krajzewicz
13 /// @author  Jakob Erdmann
14 /// @date    Tue, 04 Dec 2007
15 /// @version $Id$
16 ///
17 // A device that performs vehicle rerouting based on current edge speeds
18 /****************************************************************************/
19 #ifndef MSRoutingEngine_h
20 #define MSRoutingEngine_h
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <set>
29 #include <vector>
30 #include <map>
31 #include <utils/common/SUMOTime.h>
32 #include <utils/common/WrappingCommand.h>
33 #include <utils/router/SUMOAbstractRouter.h>
34 #include <utils/router/AStarRouter.h>
35 #include <microsim/MSVehicle.h>
36 #include "MSDevice.h"
37 
38 #ifdef HAVE_FOX
39 #include <utils/foxtools/FXWorkerThread.h>
40 #endif
41 
42 
43 // ===========================================================================
44 // class definitions
45 // ===========================================================================
46 /**
47  * @class MSRoutingEngine
48  * @brief A device that performs vehicle rerouting based on current edge speeds
49  *
50  * The routing-device system consists of in-vehicle devices that perform a routing
51  *  and a simulation-wide (static) methods for colecting edge weights.
52  *
53  * The edge weights container "myEdgeSpeeds" is pre-initialised as soon as one
54  *  device is built and is kept updated via an event that adapts it to the current
55  *  mean speed on the simulated network's edges.
56  *
57  * A device is assigned to a vehicle using the common explicit/probability - procedure.
58  *
59  * A device computes a new route for a vehicle as soon as the vehicle is inserted
60  *  (within "enterLaneAtInsertion") - and, if the given period is larger than 0 - each
61  *  x time steps where x is the period. This is triggered by an event that executes
62  *  "wrappedRerouteCommandExecute".
63  */
64 class MSRoutingEngine {
65 public:
66     /// @brief intialize period edge weight update
67     static void initWeightUpdate();
68 
69     /// @brief initialize the edge weights if not done before
70     static void initEdgeWeights();
71 
72     /// @brief returns whether any routing actions take place
hasEdgeUpdates()73     static bool hasEdgeUpdates() {
74         return myEdgeWeightSettingCommand != nullptr;
75     }
76 
77     /// @brief Information when the last edge weight adaptation occurred
getLastAdaptation()78     static SUMOTime getLastAdaptation() {
79         return myLastAdaptation;
80     }
81 
82     /// @brief return the cached route or nullptr on miss
83     static const MSRoute* getCachedRoute(const std::pair<const MSEdge*, const MSEdge*>& key);
84 
85     /// @brief initiate the rerouting, create router / thread pool on first use
86     static void reroute(SUMOVehicle& vehicle, const SUMOTime currentTime, const bool onInit);
87 
88     /// @brief adapt the known travel time for an edge
89     static void setEdgeTravelTime(const MSEdge* const edge, const double travelTime);
90 
91     /// @brief deletes the router instance
92     static void cleanup();
93 
94     /// @brief returns whether any routing actions take place
isEnabled()95     static bool isEnabled() {
96         return !myWithTaz && myAdaptationInterval >= 0;
97     }
98 
99     /// @brief return the router instance
100     static SUMOAbstractRouter<MSEdge, SUMOVehicle>& getRouterTT(
101         const MSEdgeVector& prohibited = MSEdgeVector());
102 
103     /** @brief Returns the effort to pass an edge
104     *
105     * This method is given to the used router in order to obtain the efforts
106     *  to pass an edge from the internal edge weights container.
107     *
108     * The time is not used, here, as the current simulation state is
109     *  used in an aggregated way.
110     *
111     * @param[in] e The edge for which the effort to be passed shall be returned
112     * @param[in] v The vehicle that is rerouted
113     * @param[in] t The time for which the effort shall be returned
114     * @return The effort (time to pass in this case) for an edge
115     * @see DijkstraRouter_ByProxi
116     */
117     static double getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t);
118 
119     /// @brief return current travel speed assumption
120     static double getAssumedSpeed(const MSEdge* edge);
121 
122 #ifdef HAVE_FOX
123     static void waitForAll();
lock()124     static void lock() {
125         myThreadPool.lock();
126     }
unlock()127     static void unlock() {
128         myThreadPool.unlock();
129     }
isParallel()130     static bool isParallel() {
131         return myThreadPool.size() > 0;
132     }
133 #endif
134 
135 
136 private:
137 #ifdef HAVE_FOX
138     /**
139      * @class WorkerThread
140      * @brief the thread which provides the router instance as context
141      */
142     class WorkerThread : public FXWorkerThread {
143     public:
WorkerThread(FXWorkerThread::Pool & pool,SUMOAbstractRouter<MSEdge,SUMOVehicle> * router)144         WorkerThread(FXWorkerThread::Pool& pool,
145                      SUMOAbstractRouter<MSEdge, SUMOVehicle>* router)
146             : FXWorkerThread(pool), myRouter(router) {}
getRouter()147         SUMOAbstractRouter<MSEdge, SUMOVehicle>& getRouter() const {
148             return *myRouter;
149         }
~WorkerThread()150         virtual ~WorkerThread() {
151             stop();
152             delete myRouter;
153         }
154     private:
155         SUMOAbstractRouter<MSEdge, SUMOVehicle>* myRouter;
156     };
157 
158     /**
159      * @class RoutingTask
160      * @brief the routing task which mainly calls reroute of the vehicle
161      */
162     class RoutingTask : public FXWorkerThread::Task {
163     public:
RoutingTask(SUMOVehicle & v,const SUMOTime time,const bool onInit)164         RoutingTask(SUMOVehicle& v, const SUMOTime time, const bool onInit)
165             : myVehicle(v), myTime(time), myOnInit(onInit) {}
166         void run(FXWorkerThread* context);
167     private:
168         SUMOVehicle& myVehicle;
169         const SUMOTime myTime;
170         const bool myOnInit;
171     private:
172         /// @brief Invalidated assignment operator.
173         RoutingTask& operator=(const RoutingTask&);
174     };
175 #endif
176 
177     /// @name Network state adaptation
178     /// @{
179 
180     /** @brief Adapt edge efforts by the current edge states
181      *
182      * This method is called by the event handler at the end of a simulation
183      *  step. The current edge weights are combined with the previously stored.
184      *
185      * @param[in] currentTime The current simulation time
186      * @return The offset to the next call (always 1 in this case - edge weights are updated each time step)
187      * @todo Describe how the weights are adapted
188      * @see MSEventHandler
189      * @see StaticCommand
190      */
191     static SUMOTime adaptEdgeEfforts(SUMOTime currentTime);
192     /// @}
193 
194 
195 private:
196     /// @brief The weights adaptation/overwriting command
197     static Command* myEdgeWeightSettingCommand;
198 
199     /// @brief The container of edge speeds
200     static std::vector<double> myEdgeSpeeds;
201 
202     /// @brief Information which weight prior edge efforts have
203     static double myAdaptationWeight;
204 
205     /// @brief At which time interval the edge weights get updated
206     static SUMOTime myAdaptationInterval;
207 
208     /// @brief Information when the last edge weight adaptation occurred
209     static SUMOTime myLastAdaptation;
210 
211     /// @brief The number of steps for averaging edge speeds (ring-buffer)
212     static int myAdaptationSteps;
213 
214     /// @brief The current index in the pastEdgeSpeed ring-buffer
215     static int myAdaptationStepsIndex;
216 
217     /// @brief The container of edge speeds
218     static std::vector<std::vector<double> > myPastEdgeSpeeds;
219 
220     /// @brief whether taz shall be used at initial rerouting
221     static bool myWithTaz;
222 
223     /// @brief The router to use
224     static SUMOAbstractRouter<MSEdge, SUMOVehicle>* myRouter;
225 
226     /// @brief The router to use by rerouter elements
227     static AStarRouter<MSEdge, SUMOVehicle, SUMOAbstractRouterPermissions<MSEdge, SUMOVehicle> >* myRouterWithProhibited;
228 
229     /// @brief The container of pre-calculated routes
230     static std::map<std::pair<const MSEdge*, const MSEdge*>, const MSRoute*> myCachedRoutes;
231 
232 #ifdef HAVE_FOX
233     static FXWorkerThread::Pool myThreadPool;
234 #endif
235 
236 private:
237     /// @brief Invalidated copy constructor.
238     MSRoutingEngine(const MSRoutingEngine&);
239 
240     /// @brief Invalidated assignment operator.
241     MSRoutingEngine& operator=(const MSRoutingEngine&);
242 
243 
244 };
245 
246 
247 #endif
248 
249 /****************************************************************************/
250 
251