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