Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2005-2025 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 : /****************************************************************************/
14 : /// @file MSCalibrator.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Tue, May 2005
19 : ///
20 : // Calibrates the flow on an edge by removing an inserting vehicles
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <vector>
27 : #include <utils/common/Command.h>
28 : #include <microsim/MSRouteHandler.h>
29 : #include <microsim/output/MSMeanData_Net.h>
30 : #include <microsim/output/MSDetectorFileOutput.h>
31 :
32 :
33 : // ===========================================================================
34 : // class declarations
35 : // ===========================================================================
36 : class OutputDevice;
37 : class MSRouteProbe;
38 :
39 :
40 : // ===========================================================================
41 : // class definitions
42 : // ===========================================================================
43 : /**
44 : * @class MSCalibrator
45 : * @brief Calibrates the flow on a segment to a specified one
46 : */
47 : class MSCalibrator : public MSRouteHandler, public Command, public MSDetectorFileOutput {
48 : public:
49 : /** constructor */
50 : MSCalibrator(const std::string& id,
51 : MSEdge* const edge,
52 : MSLane* const lane,
53 : MSJunction* const node,
54 : const double pos,
55 : const std::string& aXMLFilename,
56 : const std::string& outputFilename,
57 : const SUMOTime freq, const double length,
58 : const MSRouteProbe* probe,
59 : const double invalidJamThreshold,
60 : const std::string& vTypes,
61 : const bool local,
62 : const bool addLaneMeanData);
63 :
64 : /** destructor */
65 : virtual ~MSCalibrator();
66 :
67 : /** @brief Write the generated output to the given device
68 : * @param[in] dev The output device to write the data into
69 : * @param[in] startTime First time step the data were gathered
70 : * @param[in] stopTime Last time step the data were gathered
71 : * @exception IOError If an error on writing occurs
72 : */
73 : void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
74 :
75 :
76 : /** @brief Open the XML-output
77 : *
78 : * The implementing function should open an xml element using
79 : * OutputDevice::writeXMLHeader.
80 : *
81 : * @param[in] dev The output device to write the root into
82 : * @exception IOError If an error on writing occurs
83 : */
84 : void writeXMLDetectorProlog(OutputDevice& dev) const;
85 :
86 : /** the implementation of the MSTrigger / Command interface.
87 : Calibrating takes place here. */
88 : virtual SUMOTime execute(SUMOTime currentTime);
89 :
90 : /// @brief cleanup remaining data structures
91 : static void cleanup();
92 :
93 : /// @brief return all calibrator instances
94 : static const std::map<std::string, MSCalibrator*>& getInstances() {
95 : return myInstances;
96 : }
97 :
98 : struct AspiredState {
99 701 : AspiredState() : begin(-1), end(-1), q(-1.), v(-1.), vehicleParameter(0) {}
100 : SUMOTime begin;
101 : SUMOTime end;
102 : double q;
103 : double v;
104 : SUMOVehicleParameter* vehicleParameter;
105 : };
106 :
107 : AspiredState getCurrentStateInterval() const;
108 :
109 : const MSEdge* getEdge() const {
110 104 : return myEdge;
111 : }
112 :
113 : const MSLane* getLane() const {
114 1179 : return myLane;
115 : }
116 :
117 : const MSRouteProbe* getRouteProbe() const {
118 18 : return myProbe;
119 : }
120 :
121 586873 : inline virtual int passed() const {
122 : // calibrator measures at start of segment
123 : // vehicles drive to the end of an edge by default so they count as passed
124 : // but vaporized vehicles do not count
125 : // if the calibrator is located on a short edge, the vehicles are
126 : // vaporized on the next edge so we cannot rely on myEdgeMeanData.nVehVaporized
127 586873 : return myEdgeMeanData.nVehEntered + myEdgeMeanData.nVehDeparted - myClearedInJam - myRemoved;
128 : }
129 :
130 : int getInserted() const {
131 18 : return myEdgeMeanData.nVehDeparted;
132 : }
133 :
134 : int getRemoved() const {
135 18 : return myClearedInJam + myRemoved;
136 : }
137 :
138 : void setFlow(SUMOTime begin, SUMOTime end, double vehsPerHour, double speed, SUMOVehicleParameter vehicleParameter);
139 :
140 : protected:
141 : class CalibratorCommand : public Command {
142 : public:
143 381 : CalibratorCommand(MSCalibrator* cali) :
144 381 : myCalibrator(cali) {}
145 :
146 629510 : SUMOTime execute(SUMOTime currentTime) {
147 629510 : return myCalibrator->execute(currentTime);
148 : }
149 :
150 : /** @brief Reschedule or deschedule the command when quick-loading state
151 : *
152 : * The implementations should return -1 if the command shall not be re-scheduled,
153 : * or a value >= 0 that describe the new time at which the command
154 : * shall be executed again.
155 : *
156 : * @param[in] currentTime The current simulation time
157 : * @param[in] execTime The time at which the command would have been executed
158 : * @param[in] newTime The simulation time at which the simulation is restarted
159 : * @return The time at which the command shall be executed again
160 : */
161 : SUMOTime shiftTime(SUMOTime currentTime, SUMOTime execTime, SUMOTime newTime);
162 :
163 : private:
164 : MSCalibrator* myCalibrator;
165 : };
166 :
167 :
168 : /// @name inherited from GenericSAXHandler
169 : //@{
170 :
171 : /** @brief Called on the opening of a tag;
172 : *
173 : * @param[in] element ID of the currently opened element
174 : * @param[in] attrs Attributes within the currently opened element
175 : * @exception ProcessError If something fails
176 : * @see GenericSAXHandler::myStartElement
177 : */
178 : virtual void myStartElement(int element,
179 : const SUMOSAXAttributes& attrs);
180 :
181 : /** @brief Called on the closing of a tag;
182 : *
183 : * @param[in] element ID of the currently closed element
184 : * @exception ProcessError If something fails
185 : * @see GenericSAXHandler::myEndElement
186 : */
187 : virtual void myEndElement(int element);
188 : //@}
189 :
190 :
191 :
192 : class VehicleRemover : public MSMoveReminder {
193 : public:
194 1212 : VehicleRemover(MSLane* const lane, MSCalibrator* const parent, const bool undo = false) :
195 1212 : MSMoveReminder(parent->getID(), lane, true), myParent(parent), myUndoCalibration(undo) {}
196 :
197 : /// @name inherited from MSMoveReminder
198 : //@{
199 : /** @brief Checks whether the reminder is activated by a vehicle entering the lane
200 : *
201 : * Lane change means in this case that the vehicle changes to the lane
202 : * the reminder is placed at.
203 : *
204 : * @param[in] veh The entering vehicle.
205 : * @param[in] reason how the vehicle enters the lane
206 : * @return True if vehicle enters the reminder.
207 : * @see Notification
208 : */
209 : //@}
210 : virtual bool notifyEnter(SUMOTrafficObject& veh, MSMoveReminder::Notification reason, const MSLane* enteredLane = nullptr);
211 :
212 : /** @brief Checks whether any calibrations need to be undone
213 : *
214 : * @param[in] veh The leaving vehicle.
215 : * @param[in] lastPos Position on the lane when leaving.
216 : * @param[in] reason how the vehicle leaves the lane
217 : * @see Notification
218 : *
219 : * @return True if the reminder wants to receive further info.
220 : */
221 : virtual bool notifyLeave(SUMOTrafficObject& veh, double lastPos, Notification reason, const MSLane* enteredLane = nullptr);
222 :
223 : void disable() {
224 1212 : myParent = nullptr;
225 : }
226 :
227 : private:
228 : MSCalibrator* myParent;
229 : const bool myUndoCalibration;
230 : };
231 : friend class GUICalibrator;
232 :
233 : // @return whether the current state is active (GUI)
234 : bool isActive() const {
235 213566 : return myAmActive;
236 : }
237 :
238 : protected:
239 :
240 : void intervalEnd();
241 :
242 : bool isCurrentStateActive(SUMOTime time);
243 :
244 : bool tryEmit(MSLane* lane, MSVehicle* vehicle);
245 :
246 : void init();
247 :
248 : /// @brief number of vehicles expected to pass this interval
249 : int totalWished() const;
250 :
251 : /// @brief flow in the current interval in veh/h
252 : double currentFlow() const;
253 :
254 : /// @brief measured speed in the current interval
255 : double currentSpeed() const;
256 :
257 : /* @brief returns whether the lane is jammed although it should not be
258 : * @param[in] lane The lane to check or all for negative values
259 : */
260 : bool invalidJam(int laneIndex) const;
261 :
262 0 : inline int inserted() const {
263 0 : return myInserted;
264 : }
265 0 : inline int removed() const {
266 0 : return myRemoved;
267 : }
268 0 : inline int clearedInJam() const {
269 0 : return myClearedInJam;
270 : }
271 :
272 : /* @brief returns the number of vehicles (of the current type) that still
273 : * fit on the given lane
274 : * @param[in] lane The lane to check (return the maximum of all lanes for negative values)
275 : */
276 : int remainingVehicleCapacity(int laneIndex) const;
277 :
278 : /// @brief reset collected vehicle data
279 : virtual void reset();
280 :
281 : /// @brief aggregate lane values
282 : virtual void updateMeanData();
283 :
284 : /** @brief try to schedule the given vehicle for removal. return true if it
285 : * isn't already scheduled */
286 : bool scheduleRemoval(SUMOTrafficObject* veh) {
287 : return myToRemove.insert(veh->getID()).second;
288 : }
289 :
290 :
291 : /** @brief remove any vehicles which are scheduled for removal.
292 : * return true if removals took place */
293 : bool removePending();
294 :
295 : /// @brief determine id of new vehicle from calibrator state
296 : std::string getNewVehicleID();
297 :
298 : protected:
299 : /// @brief the edge on which this calibrator lies
300 : MSEdge* const myEdge;
301 : /// @brief the lane on which this calibrator lies (nullptr if the whole edge is covered at once)
302 : MSLane* const myLane;
303 : /// @brief the junction on which this calibrator lies (nullptr if is edge or lane specific)
304 : MSJunction* const myNode;
305 : /// @brief the position on the edge where this calibrator lies
306 : const double myPos;
307 : /// @brief the route probe to retrieve routes from
308 : const MSRouteProbe* const myProbe;
309 : /// @brief dummy parent to retrieve vType filter
310 : MSMeanData_Net myMeanDataParent;
311 : /// @brief data collector for the calibrator
312 : std::vector<MSMeanData_Net::MSLaneMeanDataValues*> myLaneMeanData;
313 : /// @brief accumlated data for the whole edge
314 : MSMeanData_Net::MSLaneMeanDataValues myEdgeMeanData;
315 :
316 : /// @brief List of adaptation intervals
317 : std::vector<AspiredState> myIntervals;
318 : /// @brief Iterator pointing to the current interval
319 : std::vector<AspiredState>::const_iterator myCurrentStateInterval;
320 :
321 : std::vector<VehicleRemover*> myVehicleRemovers;
322 :
323 : /** @brief set of vehicle ids to remove
324 : * @note: we avoid keeping vehicle points because someone else might
325 : * invalidate it before look at it again (i.e. another calibrator)
326 : */
327 : std::set<std::string> myToRemove;
328 :
329 : /// @brief The device for xml statistics
330 : OutputDevice* myOutput;
331 :
332 : /// @brief The frequeny with which to check for calibration
333 : SUMOTime myFrequency;
334 : /// @brief The number of vehicles that were removed in the current interval
335 : int myRemoved;
336 : /// @brief The number of vehicles that were inserted in the current interval
337 : int myInserted;
338 : /// @brief The number of vehicles that were removed when clearin a jam
339 : int myClearedInJam;
340 : /// @brief The information whether the speed adaption has been reset
341 : bool mySpeedIsDefault;
342 : /// @brief The information whether speed was adapted in the current interval
343 : bool myDidSpeedAdaption;
344 : /// @brief The information whether init was called
345 : bool myDidInit;
346 : /// @brief The default (maximum) speed on the segment
347 : double myDefaultSpeed;
348 : /// @brief The default (maximum) speed on the segment
349 : bool myHaveWarnedAboutClearingJam;
350 :
351 : /// @brief whether the calibrator was active when last checking
352 : bool myAmActive;
353 :
354 : /// @brief relative speed threshold for detecting and clearing invalid jam
355 : double myInvalidJamThreshold;
356 :
357 : /// @brief whether the calibrator needs to undo the calibration after the edge / junction has been left
358 : bool myAmLocal;
359 :
360 : /// @brief whether the calibrator has registered an invalid jam in the last execution step
361 : bool myHaveInvalidJam;
362 :
363 : /* @brief objects which need to live longer than the MSCalibrator
364 : * instance which created them */
365 : static std::vector<MSMoveReminder*> myLeftoverReminders;
366 : static std::vector<SUMOVehicleParameter*> myLeftoverVehicleParameters;
367 : static std::map<std::string, MSCalibrator*> myInstances;
368 :
369 : };
|