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 1400 : 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 Returns the maximum stop arrival delay of public transport vehicles that are on the detector
236 : * or passed the detector in the last step or -INVALID_DOUBLE
237 : */
238 : double getArrivalDelay() const;
239 :
240 : ///@brief return last time a vehicle was on the detector
241 : SUMOTime getLastDetectionTime() const;
242 :
243 : double getOverrideTime() const {
244 186358 : return myOverrideTime;
245 : }
246 : //@}
247 :
248 :
249 : /* @brief Persistently overrides the measured time since detection with the given value.
250 : * Setting a negative value resets the override
251 : */
252 : void overrideTimeSinceDetection(double time);
253 :
254 : /* @brief loads the time since detetion (from state)
255 : */
256 : void loadTimeSinceLastDetection(double time);
257 :
258 : /// @name Methods inherited from MSDetectorFileOutput.
259 : /// @{
260 :
261 : /** @brief Writes collected values into the given stream
262 : *
263 : * @param[in] dev The output device to write the data into
264 : * @param[in] startTime First time step the data were gathered
265 : * @param[in] stopTime Last time step the data were gathered
266 : * @see MSDetectorFileOutput::writeXMLOutput
267 : * @exception IOError If an error on writing occurs (!!! not yet implemented)
268 : */
269 : void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
270 :
271 :
272 : /** @brief Opens the XML-output using "detector" as root element
273 : *
274 : * @param[in] dev The output device to write the root into
275 : * @see MSDetectorFileOutput::writeXMLDetectorProlog
276 : * @exception IOError If an error on writing occurs (!!! not yet implemented)
277 : */
278 : void writeXMLDetectorProlog(OutputDevice& dev) const;
279 :
280 : /** @brief Updates the detector (computes values)
281 : * only used when detecting persons
282 : *
283 : * @param[in] step The current time step
284 : */
285 : void detectorUpdate(const SUMOTime step);
286 : /// @}
287 :
288 :
289 : /** @brief Struct to store the data of the counted vehicle internally.
290 : *
291 : * These data is fed into a container.
292 : *
293 : * @see myVehicleDataCont
294 : */
295 1407561 : struct VehicleData {
296 : /** @brief Constructor
297 : *
298 : * Used if the vehicle has left the induction loop completely
299 : *
300 : * @param[in] vehLength The length of the vehicle
301 : * @param[in] entryTimestep The time at which the vehicle entered the detector
302 : * @param[in] leaveTimestep The time at which the vehicle left the detector
303 : * @param[in] leftEarly Whether the vehicle left the detector with a lane change / teleport etc.
304 : * @param[in] detLength The length of the detector in meters
305 : */
306 : VehicleData(const SUMOTrafficObject& v, double entryTimestep,
307 : double leaveTimestep, const bool leftEarly, const double detLength = 0);
308 :
309 : /// @brief The id of the vehicle
310 : std::string idM;
311 : /// @brief Length of the vehicle
312 : double lengthM;
313 : /// @brief Entry-time of the vehicle in [s]
314 : double entryTimeM;
315 : /// @brief Leave-time of the vehicle in [s]
316 : double leaveTimeM;
317 : /// @brief Speed of the vehicle in [m/s]
318 : double speedM;
319 : /// @brief Type of the vehicle
320 : std::string typeIDM;
321 : /// @brief whether the vehicle left the detector with a lane change / teleport etc.
322 : bool leftEarlyM;
323 : };
324 :
325 :
326 : /** @brief Returns vehicle data for vehicles that have been on the detector starting at the given time
327 : *
328 : * @param[in] t The time from which vehicles shall be counted
329 : * @param[in] leaveTime Whether entryTime or leaveTime shall be compared against t
330 : * (the latter gives a more complete picture but may include vehicles in multiple steps even if they did not stay on the detector)
331 : * @return The list of vehicles
332 : */
333 : std::vector<VehicleData> collectVehiclesOnDet(SUMOTime t, bool includeEarly = false, bool leaveTime = false, bool forOccupancy = false, bool lastInterval = false) const;
334 :
335 : /// @brief allows for special color in the gui version
336 669075 : virtual void setSpecialColor(const RGBColor* /*color*/) {};
337 :
338 36 : virtual void setVisible(bool /*show*/) {};
339 :
340 : /** @brief Remove all vehicles before quick-loading state */
341 : virtual void clearState(SUMOTime time);
342 :
343 : protected:
344 : /// @name Function for summing up values
345 : ///@{
346 :
347 : /// @brief Adds up VehicleData::speedM
348 3101 : static inline double speedSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
349 3101 : return sumSoFar + data.speedM;
350 : }
351 :
352 : /// @brief Adds up VehicleData::lengthM
353 29 : static inline double lengthSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
354 29 : return sumSoFar + data.lengthM;
355 : }
356 : ///@}
357 :
358 : /// @brief helper function for mapping person movement
359 : void notifyMovePerson(MSTransportable* p, int dir, double pos);
360 :
361 : protected:
362 : /// @brief detecto name
363 : std::string myName;
364 :
365 : /// @brief Detector's position on lane [m]
366 : const double myPosition;
367 :
368 : /// @brief Detector's end position (defaults to myPosition)
369 : const double myEndPosition;
370 :
371 : /// @brief whether internals need to be guarded against concurrent access (GUI or multi threading)
372 : const bool myNeedLock;
373 :
374 : /// @brief Leave-time of the last vehicle detected [s]
375 : double myLastLeaveTime;
376 :
377 : /// @brief overrides the time since last detection
378 : double myOverrideTime;
379 :
380 : /// @brief records the time at which overrideTimeSinceDetection was activated
381 : double myOverrideEntryTime;
382 :
383 : /// @brief The number of entered vehicles
384 : int myEnteredVehicleNumber;
385 :
386 : /// @brief Type of myVehicleDataCont.
387 : typedef std::deque< VehicleData > VehicleDataCont;
388 :
389 : /// @brief Data of vehicles that have completely passed the detector
390 : VehicleDataCont myVehicleDataCont;
391 :
392 : /// @brief Data of vehicles that have completely passed the detector in the last time interval
393 : VehicleDataCont myLastVehicleDataCont;
394 :
395 : /// @brief Data for vehicles that have entered the detector (vehicle -> enter time)
396 : std::map<SUMOTrafficObject*, double> myVehiclesOnDet;
397 :
398 : SUMOTime myLastIntervalEnd;
399 : SUMOTime myLastIntervalBegin;
400 :
401 : private:
402 : /// @brief Invalidated copy constructor.
403 : MSInductLoop(const MSInductLoop&);
404 :
405 : /// @brief Invalidated assignment operator.
406 : MSInductLoop& operator=(const MSInductLoop&);
407 :
408 :
409 : };
|