Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2004-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 : /****************************************************************************/
14 : /// @file MSInductLoop.h
15 : /// @author Christian Roessel
16 : /// @author Daniel Krajzewicz
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @author Jakob Erdmann
20 : /// @author Mirko Barthauer
21 : /// @date 2004-11-23
22 : ///
23 : // An unextended detector measuring at a fixed position on a fixed lane.
24 : /****************************************************************************/
25 : #pragma once
26 : #include <config.h>
27 :
28 : #include <string>
29 : #include <deque>
30 : #include <map>
31 : #include <functional>
32 : #include <microsim/MSMoveReminder.h>
33 : #include <microsim/output/MSDetectorFileOutput.h>
34 :
35 :
36 : // ===========================================================================
37 : // class declarations
38 : // ===========================================================================
39 : class MSLane;
40 : class MSVehicle;
41 : class OutputDevice;
42 :
43 :
44 : // ===========================================================================
45 : // class definitions
46 : // ===========================================================================
47 : /**
48 : * @class MSInductLoop
49 : * @brief An unextended detector measuring at a fixed position on a fixed lane.
50 : *
51 : * Only vehicles that passed the entire detector are counted. We
52 : * ignore vehicles that are emitted onto the detector and vehicles
53 : * that change their lane while they are on the detector, because we
54 : * cannot determine a meaningful enter/leave-times.
55 : *
56 : * This detector uses the MSMoveReminder mechanism, i.e. the vehicles
57 : * call the detector if they pass it.
58 : *
59 : * @see MSMoveReminder
60 : * @see MSDetectorFileOutput
61 : */
62 : class MSInductLoop
63 : : public MSMoveReminder, public MSDetectorFileOutput {
64 : public:
65 : /**
66 : * @brief Constructor.
67 : *
68 : * Adds reminder to MSLane.
69 : *
70 : * @param[in] id Unique id
71 : * @param[in] lane Lane where detector works on
72 : * @param[in] position Position of the detector within the lane
73 : * @param[in] vTypes which vehicle types are considered
74 : * @param[in] needLocking whether internals need to be guarded against concurrent access (GUI)
75 : */
76 : MSInductLoop(const std::string& id, MSLane* const lane,
77 : double positionInMeters,
78 : double length, std::string name,
79 : const std::string& vTypes,
80 : const std::string& nextEdges,
81 : int detectPersons,
82 : const bool needLocking);
83 :
84 :
85 : /// @brief Destructor
86 : ~MSInductLoop();
87 :
88 :
89 : /// @brief Resets all generated values to allow computation of next interval
90 : virtual void reset();
91 :
92 : /// @brief get name
93 : std::string getName() const {
94 : return myName;
95 : }
96 :
97 : /** @brief Returns the position of the detector on the lane
98 : * @return The detector's position in meters
99 : */
100 : double getPosition() const {
101 536 : return myPosition;
102 : }
103 :
104 : /** @brief Returns the end position of the detector on the lane
105 : * @return The detector's end position in meters
106 : */
107 : double getEndPosition() const {
108 1382 : return myEndPosition;
109 : }
110 :
111 :
112 : /// @name Methods inherited from MSMoveReminder
113 : /// @{
114 : /** @brief Checks whether the reminder is activated by a vehicle entering the lane
115 : *
116 : * Lane change means in this case that the vehicle changes to the lane
117 : * the reminder is placed at.
118 : *
119 : * @param[in] veh The entering vehicle.
120 : * @param[in] reason how the vehicle enters the lane
121 : * @return True if vehicle enters the induction loop
122 : * @see Notification
123 : */
124 : bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane = 0);
125 :
126 : /** @brief Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder
127 : *
128 : * As soon a vehicle enters the detector, its entry time is computed and stored
129 : * in myVehiclesOnDet via enterDetectorByMove. If it passes the detector, the
130 : * according leaving time is computed and stored, too, using leaveDetectorByMove.
131 : *
132 : * @param[in] veh Vehicle that asks this remider.
133 : * @param[in] oldPos Position before move.
134 : * @param[in] newPos Position after move with newSpeed.
135 : * @param[in] newSpeed Moving speed.
136 : * @return True if vehicle hasn't passed the detector completely.
137 : * @see MSMoveReminder
138 : * @see MSMoveReminder::notifyMove
139 : * @see enterDetectorByMove
140 : * @see leaveDetectorByMove
141 : */
142 : bool notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed);
143 :
144 :
145 : /** @brief Dismisses the vehicle if it is on the detector due to a lane change
146 : *
147 : * If the vehicle is on the detector, it will be dismissed by incrementing
148 : * myDismissedVehicleNumber and removing this vehicle's entering time from
149 : * myVehiclesOnDet.
150 : *
151 : * @param[in] veh The leaving vehicle.
152 : * @param[in] lastPos Position on the lane when leaving.
153 : * @param[in] isArrival whether the vehicle arrived at its destination
154 : * @param[in] isLaneChange whether the vehicle changed from the lane
155 : * @see discardVehicle
156 : * @see MSMoveReminder
157 : * @see MSMoveReminder::notifyLeave
158 : */
159 : bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
160 :
161 :
162 : //@}
163 :
164 :
165 :
166 : /// @name Methods returning current values
167 : /// @{
168 :
169 : /** @brief Returns the speed of the vehicle on the detector
170 : *
171 : * If no vehicle is on the detector, -1 is returned, otherwise
172 : * this vehicle's current speed.
173 : *
174 : * @return The speed [m/s] of the vehicle if one is on the detector, -1 otherwise
175 : */
176 : double getSpeed(const int offset) const;
177 :
178 :
179 : /** @brief Returns the length of the vehicle on the detector
180 : *
181 : * If no vehicle is on the detector, -1 is returned, otherwise
182 : * this vehicle's length.
183 : *
184 : * @return The length [m] of the vehicle if one is on the detector, -1 otherwise
185 : */
186 : double getVehicleLength(const int offset) const;
187 :
188 :
189 : /** @brief Returns the current occupancy
190 : *
191 : * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
192 : * in this timestep, its occupancy value is returned. If no vehicle has passed,
193 : * 0 is returned.
194 : *
195 : * @return This detector's current occupancy
196 : * @todo recheck (especially if more than one vehicle has passed)
197 : */
198 : double getOccupancy() const;
199 :
200 : /** @brief Returns the number of vehicles that have passed the detector
201 : *
202 : * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
203 : * in this timestep, 1 is returned. If no vehicle has passed,
204 : * 0 is returned.
205 : *
206 : * @return The number of vehicles that have passed the detector
207 : * @todo recheck (especially if more than one vehicle has passed)
208 : */
209 : double getEnteredNumber(const int offset) const;
210 :
211 :
212 : /** @brief Returns the ids of vehicles that have passed the detector
213 : *
214 : * @return The ids of vehicles that have passed the detector
215 : * @todo recheck (especially if more than one vehicle has passed)
216 : */
217 : std::vector<std::string> getVehicleIDs(const int offset) const;
218 :
219 : double getIntervalOccupancy(bool lastInterval = false) const;
220 : double getIntervalMeanSpeed(bool lastInterval = false) const;
221 : int getIntervalVehicleNumber(bool lastInterval = false) const;
222 : std::vector<std::string> getIntervalVehicleIDs(bool lastInterval = false) const;
223 :
224 : /** @brief Returns the time since the last vehicle left the detector
225 : *
226 : * @return seconds from last leaving (detection) of the detector
227 : */
228 : double getTimeSinceLastDetection() const;
229 :
230 : /** @brief Returns the time of continous occupation by the same vehicle in seconds
231 : * or 0 if there is no vehicle on the detector
232 : */
233 : double getOccupancyTime() const;
234 :
235 : ///@brief return last time a vehicle was on the detector
236 : SUMOTime getLastDetectionTime() const;
237 :
238 : double getOverrideTime() const {
239 184700 : return myOverrideTime;
240 : }
241 : //@}
242 :
243 :
244 : /* @brief Persistently overrides the measured time since detection with the given value.
245 : * Setting a negative value resets the override
246 : */
247 : void overrideTimeSinceDetection(double time);
248 :
249 : /* @brief loads the time since detetion (from state)
250 : */
251 : void loadTimeSinceLastDetection(double time);
252 :
253 : /// @name Methods inherited from MSDetectorFileOutput.
254 : /// @{
255 :
256 : /** @brief Writes collected values into the given stream
257 : *
258 : * @param[in] dev The output device to write the data into
259 : * @param[in] startTime First time step the data were gathered
260 : * @param[in] stopTime Last time step the data were gathered
261 : * @see MSDetectorFileOutput::writeXMLOutput
262 : * @exception IOError If an error on writing occurs (!!! not yet implemented)
263 : */
264 : void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
265 :
266 :
267 : /** @brief Opens the XML-output using "detector" as root element
268 : *
269 : * @param[in] dev The output device to write the root into
270 : * @see MSDetectorFileOutput::writeXMLDetectorProlog
271 : * @exception IOError If an error on writing occurs (!!! not yet implemented)
272 : */
273 : void writeXMLDetectorProlog(OutputDevice& dev) const;
274 :
275 : /** @brief Updates the detector (computes values)
276 : * only used when detecting persons
277 : *
278 : * @param[in] step The current time step
279 : */
280 : void detectorUpdate(const SUMOTime step);
281 : /// @}
282 :
283 :
284 : /** @brief Struct to store the data of the counted vehicle internally.
285 : *
286 : * These data is fed into a container.
287 : *
288 : * @see myVehicleDataCont
289 : */
290 1398630 : struct VehicleData {
291 : /** @brief Constructor
292 : *
293 : * Used if the vehicle has left the induction loop completely
294 : *
295 : * @param[in] vehLength The length of the vehicle
296 : * @param[in] entryTimestep The time at which the vehicle entered the detector
297 : * @param[in] leaveTimestep The time at which the vehicle left the detector
298 : * @param[in] leftEarly Whether the vehicle left the detector with a lane change / teleport etc.
299 : * @param[in] detLength The length of the detector in meters
300 : */
301 : VehicleData(const SUMOTrafficObject& v, double entryTimestep,
302 : double leaveTimestep, const bool leftEarly, const double detLength = 0);
303 :
304 : /// @brief The id of the vehicle
305 : std::string idM;
306 : /// @brief Length of the vehicle
307 : double lengthM;
308 : /// @brief Entry-time of the vehicle in [s]
309 : double entryTimeM;
310 : /// @brief Leave-time of the vehicle in [s]
311 : double leaveTimeM;
312 : /// @brief Speed of the vehicle in [m/s]
313 : double speedM;
314 : /// @brief Type of the vehicle
315 : std::string typeIDM;
316 : /// @brief whether the vehicle left the detector with a lane change / teleport etc.
317 : bool leftEarlyM;
318 : };
319 :
320 :
321 : /** @brief Returns vehicle data for vehicles that have been on the detector starting at the given time
322 : *
323 : * @param[in] t The time from which vehicles shall be counted
324 : * @param[in] leaveTime Whether entryTime or leaveTime shall be compared against t
325 : * (the latter gives a more complete picture but may include vehicles in multiple steps even if they did not stay on the detector)
326 : * @return The list of vehicles
327 : */
328 : std::vector<VehicleData> collectVehiclesOnDet(SUMOTime t, bool includeEarly = false, bool leaveTime = false, bool forOccupancy = false, bool lastInterval = false) const;
329 :
330 : /// @brief allows for special color in the gui version
331 663399 : virtual void setSpecialColor(const RGBColor* /*color*/) {};
332 :
333 36 : virtual void setVisible(bool /*show*/) {};
334 :
335 : /** @brief Remove all vehicles before quick-loading state */
336 : virtual void clearState(SUMOTime time);
337 :
338 : protected:
339 : /// @name Function for summing up values
340 : ///@{
341 :
342 : /// @brief Adds up VehicleData::speedM
343 2333 : static inline double speedSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
344 2333 : return sumSoFar + data.speedM;
345 : }
346 :
347 : /// @brief Adds up VehicleData::lengthM
348 29 : static inline double lengthSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
349 29 : return sumSoFar + data.lengthM;
350 : }
351 : ///@}
352 :
353 : /// @brief helper function for mapping person movement
354 : void notifyMovePerson(MSTransportable* p, int dir, double pos);
355 :
356 : protected:
357 : /// @brief detecto name
358 : std::string myName;
359 :
360 : /// @brief Detector's position on lane [m]
361 : const double myPosition;
362 :
363 : /// @brief Detector's end position (defaults to myPosition)
364 : const double myEndPosition;
365 :
366 : /// @brief whether internals need to be guarded against concurrent access (GUI or multi threading)
367 : const bool myNeedLock;
368 :
369 : /// @brief Leave-time of the last vehicle detected [s]
370 : double myLastLeaveTime;
371 :
372 : /// @brief overrides the time since last detection
373 : double myOverrideTime;
374 :
375 : /// @brief records the time at which overrideTimeSinceDetection was activated
376 : double myOverrideEntryTime;
377 :
378 : /// @brief The number of entered vehicles
379 : int myEnteredVehicleNumber;
380 :
381 : /// @brief Type of myVehicleDataCont.
382 : typedef std::deque< VehicleData > VehicleDataCont;
383 :
384 : /// @brief Data of vehicles that have completely passed the detector
385 : VehicleDataCont myVehicleDataCont;
386 :
387 : /// @brief Data of vehicles that have completely passed the detector in the last time interval
388 : VehicleDataCont myLastVehicleDataCont;
389 :
390 : /// @brief Data for vehicles that have entered the detector (vehicle -> enter time)
391 : std::map<SUMOTrafficObject*, double> myVehiclesOnDet;
392 :
393 : SUMOTime myLastIntervalEnd;
394 : SUMOTime myLastIntervalBegin;
395 :
396 : private:
397 : /// @brief Invalidated copy constructor.
398 : MSInductLoop(const MSInductLoop&);
399 :
400 : /// @brief Invalidated assignment operator.
401 : MSInductLoop& operator=(const MSInductLoop&);
402 :
403 :
404 : };
|