1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2004-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSInductLoop.h
11 /// @author  Christian Roessel
12 /// @author  Daniel Krajzewicz
13 /// @author  Sascha Krieg
14 /// @author  Michael Behrisch
15 /// @author  Jakob Erdmann
16 /// @date    2004-11-23
17 /// @version $Id$
18 ///
19 // An unextended detector measuring at a fixed position on a fixed lane.
20 /****************************************************************************/
21 #ifndef MSInductLoop_h
22 #define MSInductLoop_h
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #include <config.h>
29 
30 #include <string>
31 #include <deque>
32 #include <map>
33 #include <functional>
34 #include <microsim/MSMoveReminder.h>
35 #include <microsim/output/MSDetectorFileOutput.h>
36 
37 
38 // ===========================================================================
39 // class declarations
40 // ===========================================================================
41 class MSLane;
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      */
77     MSInductLoop(const std::string& id, MSLane* const lane,
78                  double positionInMeters,
79                  const std::string& vTypes);
80 
81 
82     /// @brief Destructor
83     ~MSInductLoop();
84 
85 
86     /** @brief Resets all generated values to allow computation of next interval
87      */
88     virtual void reset();
89 
90 
91     /** @brief Returns the position of the detector on the lane
92      * @return The detector's position in meters
93      */
getPosition()94     double getPosition() const {
95         return myPosition;
96     }
97 
98 
99     /// @name Methods inherited from MSMoveReminder
100     /// @{
101     /** @brief Checks whether the reminder is activated by a vehicle entering the lane
102      *
103      * Lane change means in this case that the vehicle changes to the lane
104      *  the reminder is placed at.
105      *
106      * @param[in] veh The entering vehicle.
107      * @param[in] reason how the vehicle enters the lane
108      * @return True if vehicle enters the induction loop
109      * @see Notification
110      */
111     bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane = 0);
112 
113     /** @brief Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder
114      *
115      * As soon a vehicle enters the detector, its entry time is computed and stored
116      *  in myVehiclesOnDet via enterDetectorByMove. If it passes the detector, the
117      *  according leaving time is computed and stored, too, using leaveDetectorByMove.
118      *
119      * @param[in] veh Vehicle that asks this remider.
120      * @param[in] oldPos Position before move.
121      * @param[in] newPos Position after move with newSpeed.
122      * @param[in] newSpeed Moving speed.
123      * @return True if vehicle hasn't passed the detector completely.
124      * @see MSMoveReminder
125      * @see MSMoveReminder::notifyMove
126      * @see enterDetectorByMove
127      * @see leaveDetectorByMove
128      */
129     bool notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed);
130 
131 
132     /** @brief Dismisses the vehicle if it is on the detector due to a lane change
133      *
134      * If the vehicle is on the detector, it will be dismissed by incrementing
135      *  myDismissedVehicleNumber and removing this vehicle's entering time from
136      *  myVehiclesOnDet.
137      *
138      * @param[in] veh The leaving vehicle.
139      * @param[in] lastPos Position on the lane when leaving.
140      * @param[in] isArrival whether the vehicle arrived at its destination
141      * @param[in] isLaneChange whether the vehicle changed from the lane
142      * @see leaveDetectorByLaneChange
143      * @see MSMoveReminder
144      * @see MSMoveReminder::notifyLeave
145      */
146     bool notifyLeave(SUMOTrafficObject& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* enteredLane = 0);
147 
148 
149     //@}
150 
151 
152 
153     /// @name Methods returning current values
154     /// @{
155 
156     /** @brief Returns the speed of the vehicle on the detector
157      *
158      * If no vehicle is on the detector, -1 is returned, otherwise
159      *  this vehicle's current speed.
160      *
161      * @return The speed [m/s] of the vehicle if one is on the detector, -1 otherwise
162      */
163     double getCurrentSpeed() const;
164 
165 
166     /** @brief Returns the length of the vehicle on the detector
167      *
168      * If no vehicle is on the detector, -1 is returned, otherwise
169      *  this vehicle's length.
170      *
171      * @return The length [m] of the vehicle if one is on the detector, -1 otherwise
172      */
173     double getCurrentLength() const;
174 
175 
176     /** @brief Returns the current occupancy
177      *
178      * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
179      *  in this timestep, its occupancy value is returned. If no vehicle has passed,
180      *  0 is returned.
181      *
182      * @return This detector's current occupancy
183      * @todo recheck (especially if more than one vehicle has passed)
184      */
185     double getCurrentOccupancy() const;
186 
187 
188     /** @brief Returns the number of vehicles that have passed the detector
189      *
190      * If a vehicle is on the detector, 1 is returned. If a vehicle has passed the detector
191      *  in this timestep, 1 is returned. If no vehicle has passed,
192      *  0 is returned.
193      *
194      * @return The number of vehicles that have passed the detector
195      * @todo recheck (especially if more than one vehicle has passed)
196      */
197     int getCurrentPassedNumber() const;
198 
199 
200     /** @brief Returns the ids of vehicles that have passed the detector
201      *
202      * @return The ids of vehicles that have passed the detector
203      * @todo recheck (especially if more than one vehicle has passed)
204      */
205     std::vector<std::string> getCurrentVehicleIDs() const;
206 
207 
208     /** @brief Returns the time since the last vehicle left the detector
209      *
210      * @return Timesteps from last leaving (detection) of the detector
211      */
212     double getTimeSinceLastDetection() const;
213     //@}
214 
215 
216 
217     /// @name Methods inherited from MSDetectorFileOutput.
218     /// @{
219 
220     /** @brief Writes collected values into the given stream
221      *
222      * @param[in] dev The output device to write the data into
223      * @param[in] startTime First time step the data were gathered
224      * @param[in] stopTime Last time step the data were gathered
225      * @see MSDetectorFileOutput::writeXMLOutput
226      * @exception IOError If an error on writing occurs (!!! not yet implemented)
227      */
228     void writeXMLOutput(OutputDevice& dev, SUMOTime startTime, SUMOTime stopTime);
229 
230 
231     /** @brief Opens the XML-output using "detector" as root element
232      *
233      * @param[in] dev The output device to write the root into
234      * @see MSDetectorFileOutput::writeXMLDetectorProlog
235      * @exception IOError If an error on writing occurs (!!! not yet implemented)
236      */
237     void writeXMLDetectorProlog(OutputDevice& dev) const;
238     /// @}
239 
240 
241 
242     /** @brief Struct to store the data of the counted vehicle internally.
243      *
244      * These data is fed into a container.
245      *
246      * @see myVehicleDataCont
247      */
248     struct VehicleData {
249         /** @brief Constructor
250          *
251          * Used if the vehicle has passed the induct loop completely
252          *
253          * @param[in] vehLength The length of the vehicle
254          * @param[in] entryTimestep The time at which the vehicle entered the detector
255          * @param[in] leaveTimestep The time at which the vehicle left the detector
256          */
VehicleDataVehicleData257         VehicleData(const std::string& id, double vehLength, double entryTimestep, double leaveTimestep,
258                     const std::string& typeID)
259             : idM(id), lengthM(vehLength), entryTimeM(entryTimestep), leaveTimeM(leaveTimestep),
260               speedM(vehLength / MAX2(leaveTimestep - entryTimestep, NUMERICAL_EPS)), typeIDM(typeID) {}
261 
262         /// @brief The id of the vehicle
263         std::string idM;
264         /// @brief Length of the vehicle
265         double lengthM;
266         /// @brief Entry-time of the vehicle in [s]
267         double entryTimeM;
268         /// @brief Leave-time of the vehicle in [s]
269         double leaveTimeM;
270         /// @brief Speed of the vehicle in [m/s]
271         double speedM;
272         /// @brief Type of the vehicle in
273         std::string typeIDM;
274     };
275 
276 
277     /** @brief Returns vehicle data for vehicles that have been on the detector starting at the given time
278      *
279      * @param[in] t The time from which vehicles shall be counted
280      * @param[in] leaveTime Whether entryTime or leaveTime shall be compared against t
281      *            (the latter gives a more complete picture but may include vehicles in multiple steps even if they did not stay on the detector)
282      * @return The list of vehicles
283      */
284     virtual std::vector<VehicleData> collectVehiclesOnDet(SUMOTime t, bool leaveTime = false) const;
285 
286     /// @brief allows for special color in the gui version
setSpecialColor(const RGBColor *)287     virtual void setSpecialColor(const RGBColor* /*color*/) {};
288 
289 protected:
290     /// @name Methods that add and remove vehicles from internal container
291     /// @{
292 
293     /** @brief Introduces a vehicle to the detector's map myVehiclesOnDet.
294      * @param veh The entering vehicle.
295      * @param entryTimestep Timestep (not necessary integer) of entrance.
296      */
297     virtual void enterDetectorByMove(SUMOTrafficObject& veh, double entryTimestep);
298 
299 
300     /** @brief Processes a vehicle that leaves the detector
301      *
302      * Removes a vehicle from the detector's map myVehiclesOnDet and
303      * adds the vehicle data to the internal myVehicleDataCont.
304      *
305      * @param veh The leaving vehicle.
306      * @param leaveTimestep Timestep (not necessary integer) of leaving.
307      */
308     virtual void leaveDetectorByMove(SUMOTrafficObject& veh, double leaveTimestep);
309 
310 
311     /** @brief Removes a vehicle from the detector's map myVehiclesOnDet.
312      * @param veh The leaving vehicle.
313      * @param lastPos The last position of the leaving vehicle.
314      */
315     virtual void leaveDetectorByLaneChange(SUMOTrafficObject& veh, double lastPos);
316     /// @}
317 
318 
319 protected:
320     /// @name Function for summing up values
321     ///@{
322 
323     /// @brief Adds up VehicleData::speedM
speedSum(double sumSoFar,const MSInductLoop::VehicleData & data)324     static inline double speedSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
325         return sumSoFar + data.speedM;
326     }
327 
328     /// @brief Adds up VehicleData::lengthM
lengthSum(double sumSoFar,const MSInductLoop::VehicleData & data)329     static inline double lengthSum(double sumSoFar, const MSInductLoop::VehicleData& data) {
330         return sumSoFar + data.lengthM;
331     }
332     ///@}
333 
334 
335 protected:
336     /// @brief Detector's position on lane [m]
337     const double myPosition;
338 
339     /// @brief Leave-time of the last vehicle detected [s]
340     double myLastLeaveTime;
341 
342     /// @brief Occupancy by the last vehicle detected.
343     double myLastOccupancy;
344 
345     /// @brief The number of entered vehicles
346     int myEnteredVehicleNumber;
347 
348 
349     /// @brief Type of myVehicleDataCont.
350     typedef std::deque< VehicleData > VehicleDataCont;
351 
352     /// @brief Data of vehicles that have completely passed the detector
353     VehicleDataCont myVehicleDataCont;
354 
355     /// @brief Data of vehicles that have completely passed the detector in the last time interval
356     VehicleDataCont myLastVehicleDataCont;
357 
358 
359     /// @brief Type of myVehiclesOnDet
360 
361     typedef std::map< SUMOTrafficObject*, double > VehicleMap;
362 
363     /// @brief Data for vehicles that have entered the detector (vehicle -> enter time)
364     VehicleMap myVehiclesOnDet;
365 
366 private:
367     /// @brief Invalidated copy constructor.
368     MSInductLoop(const MSInductLoop&);
369 
370     /// @brief Invalidated assignment operator.
371     MSInductLoop& operator=(const MSInductLoop&);
372 
373 
374 };
375 
376 
377 #endif
378 
379 /****************************************************************************/
380 
381