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