SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MSInductLoop.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // An unextended detector measuring at a fixed position on a fixed lane.
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
15 // Copyright (C) 2001-2016 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include "MSInductLoop.h"
37 #include <cassert>
38 #include <numeric>
39 #include <utility>
41 #include <utils/common/ToString.h>
43 #include <microsim/MSLane.h>
44 #include <microsim/MSVehicle.h>
45 #include <microsim/MSNet.h>
50 
51 #ifdef CHECK_MEMORY_LEAKS
52 #include <foreign/nvwa/debug_new.h>
53 #endif // CHECK_MEMORY_LEAKS
54 
55 #define HAS_NOT_LEFT_DETECTOR -1
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
60 MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
61  SUMOReal positionInMeters,
62  const std::string& vTypes) :
63  MSMoveReminder(id, lane),
64  MSDetectorFileOutput(id, vTypes),
65  myPosition(positionInMeters),
66  myLastLeaveTime(SIMTIME),
67  myVehicleDataCont(),
68  myVehiclesOnDet() {
69  assert(myPosition >= 0 && myPosition <= myLane->getLength());
70  reset();
71 }
72 
73 
75 }
76 
77 
78 void
82  myVehicleDataCont.clear();
83 }
84 
85 
86 bool
88  if (!vehicleApplies(veh)) {
89  return false;
90  }
91  if (reason == NOTIFICATION_DEPARTED ||
92  reason == NOTIFICATION_TELEPORT ||
93  reason == NOTIFICATION_PARKING ||
94  reason == NOTIFICATION_LANE_CHANGE) {
96  myVehiclesOnDet.insert(std::make_pair(&veh, SIMTIME));
98  }
99  }
100  return true;
101 }
102 
103 
104 bool
106  SUMOReal newPos, SUMOReal newSpeed) {
107  if (newPos < myPosition) {
108  // detector not reached yet
109  return true;
110  }
111  const SUMOReal oldSpeed = veh.getPreviousSpeed();
112  if (newPos >= myPosition && oldPos < myPosition) {
113  // entered the detector by move
114  const SUMOReal timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
115  SUMOReal entryTime = SIMTIME + timeBeforeEnter;
116  enterDetectorByMove(veh, entryTime);
117  }
118  SUMOReal oldBackPos = oldPos - veh.getVehicleType().getLength();
119  SUMOReal newBackPos = newPos - veh.getVehicleType().getLength();
120  if (newBackPos > myPosition) {
121  // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
122  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
123  if (oldBackPos <= myPosition) {
124  const SUMOReal timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, newBackPos, oldSpeed, newSpeed);
125  const SUMOReal leaveTime = SIMTIME + timeBeforeLeave;
126  leaveDetectorByMove(veh, leaveTime);
127  } else {
128  // vehicle is already beyond the detector...
129  // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
130  // XXX: would we need to call leaveDetectorByMove(veh, leaveTime) as it was done before
131  // I inserted this if-else differentiation? (Leo) It seems that such a call only resets
132  // the last leave Time, which seems inadequate to do for such a situation (though it actually
133  // appears in test output/e1/one_vehicle/lane_change). Moreover, if the vehicle was
134  // not removed, this call would tidy up.
135  // XXX: Indeed, we need to tidy up, e.g., in case of teleport insertion behind detector
136  // XXX: As a quickfix we just remove it. (should be discussed! Leo) Refs. #2579
137 
138  myVehiclesOnDet.erase(&veh);
139  }
140  return false;
141  }
142  // vehicle stays on the detector
143  return true;
144 }
145 
146 
147 bool
150  leaveDetectorByLaneChange(veh, lastPos);
151  return false;
152  }
153  return true;
154 }
155 
156 
157 SUMOReal
159  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
160  return d.size() != 0
161  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
162  : -1;
163 }
164 
165 
166 SUMOReal
168  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
169  return d.size() != 0
170  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
171  : -1;
172 }
173 
174 
175 SUMOReal
178  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
179  if (d.size() == 0) {
180  return -1;
181  }
182  SUMOReal occupancy = 0;
183  SUMOReal csecond = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
184  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
185  const SUMOReal leaveTime = (*i).leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : (*i).leaveTimeM;
186  const SUMOReal timeOnDetDuringInterval = leaveTime - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
187  occupancy += MIN2(timeOnDetDuringInterval, TS);
188  }
189  return occupancy / TS * (SUMOReal) 100.;
190 }
191 
192 
193 int
195  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
196  return (int) d.size();
197 }
198 
199 
200 std::vector<std::string>
202  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
203  std::vector<std::string> ret;
204  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
205  ret.push_back((*i).idM);
206  }
207  return ret;
208 }
209 
210 
211 SUMOReal
213  if (myVehiclesOnDet.size() != 0) {
214  // detector is occupied
215  return 0;
216  }
217  return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
218 }
219 
220 
221 void
223  dev.writeXMLHeader("detector", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/det_e1_file.xsd\"");
224 }
225 
226 
227 void
229  SUMOTime startTime, SUMOTime stopTime) {
230  const SUMOReal t(STEPS2TIME(stopTime - startTime));
231  const SUMOReal flow = ((SUMOReal)myVehicleDataCont.size() / t) * (SUMOReal) 3600.0;
232  SUMOReal occupancy = 0.;
233  SUMOReal speedSum = 0.;
234  SUMOReal lengthSum = 0.;
235  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
236  const SUMOReal timeOnDetDuringInterval = i->leaveTimeM - MAX2(STEPS2TIME(startTime), i->entryTimeM);
237  occupancy += MIN2(timeOnDetDuringInterval, t);
238  speedSum += i->speedM;
239  lengthSum += i->lengthM;
240  }
241  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
242  occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
243  }
244  occupancy = occupancy / t * (SUMOReal) 100.;
245  const SUMOReal meanSpeed = myVehicleDataCont.size() != 0 ? speedSum / (SUMOReal)myVehicleDataCont.size() : -1;
246  const SUMOReal meanLength = myVehicleDataCont.size() != 0 ? lengthSum / (SUMOReal)myVehicleDataCont.size() : -1;
249  dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed);
250  dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
251  reset();
252 }
253 
254 
255 void
257  SUMOReal entryTimestep) {
258 // // Debug (Leo)
259 // std::cout << "enterDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
260 
261  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
263 }
264 
265 
266 void
268  SUMOReal leaveTimestep) {
269 
270 // // Debug (Leo)
271 // std::cout << "leaveDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
272 
273  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
274  if (it != myVehiclesOnDet.end()) {
275  SUMOReal entryTimestep = it->second;
276  myVehiclesOnDet.erase(it);
277  assert(entryTimestep < leaveTimestep);
278  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
279  myLastOccupancy = leaveTimestep - entryTimestep;
280  }
281  // XXX: why is this outside the conditional block? (Leo)
282  myLastLeaveTime = leaveTimestep;
283 }
284 
285 
286 void
288 
289 // // Debug (Leo)
290 // std::cout << "leaveDetectorByLaneChange(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
291 
292  // Discard entry data
293  myVehiclesOnDet.erase(&veh);
294 }
295 
296 
297 std::vector<MSInductLoop::VehicleData>
298 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool leaveTime) const {
299  SUMOReal t = STEPS2TIME(tMS);
300  std::vector<VehicleData> ret;
301  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
302  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
303  ret.push_back(*i);
304  }
305  }
306  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
307  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
308  ret.push_back(*i);
309  }
310  }
311  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
312  SUMOVehicle* v = (*i).first;
314  d.speedM = v->getSpeed();
315  ret.push_back(d);
316  }
317  return ret;
318 }
319 
320 
321 /****************************************************************************/
322 
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:257
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
long long int SUMOTime
Definition: SUMOTime.h:43
The vehicle arrived at a junction.
MSLane *const myLane
Lane on which the reminder works.
virtual SUMOReal getPositionOnLane() const =0
Get the vehicle's position along the lane.
bool vehicleApplies(const SUMOVehicle &veh) const
Checks whether the detector measures vehicles of the given type.
virtual void reset()
Resets all generated values to allow computation of next interval.
static std::string escapeXML(const std::string &orig)
Replaces the standard escapes by their XML entities.
Notification
Definition of a vehicle state.
SUMOReal getLength() const
Get vehicle's length [m].
virtual SUMOReal getPreviousSpeed() const =0
Returns the vehicle's previous speed.
int getCurrentPassedNumber() const
Returns the number of vehicles that have passed the detector.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:159
T MAX2(T a, T b)
Definition: StdDefs.h:75
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
virtual std::vector< VehicleData > collectVehiclesOnDet(SUMOTime t, bool leaveTime=false) const
Returns vehicle data for vehicles that have been on the detector starting at the given time...
SUMOReal getCurrentOccupancy() const
Returns the current occupancy.
#define TS
Definition: SUMOTime.h:52
VehicleMap myVehiclesOnDet
Data for vehicles that have entered the detector (vehicle -> enter time)
Definition: MSInductLoop.h:368
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:254
VehicleDataCont myLastVehicleDataCont
Data of vehicles that have completely passed the detector in the last time interval.
Definition: MSInductLoop.h:361
const SUMOReal myPosition
Detector's position on lane [m].
Definition: MSInductLoop.h:342
#define SIMTIME
Definition: SUMOTime.h:70
void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "detector" as root element.
VehicleDataCont myVehicleDataCont
Data of vehicles that have completely passed the detector.
Definition: MSInductLoop.h:358
SUMOReal speedM
Speed of the vehicle in [m/s].
Definition: MSInductLoop.h:278
bool writeXMLHeader(const std::string &rootElement, const std::string &attrs="", const std::string &comment="")
Writes an XML header with optional configuration.
static SUMOReal lengthSum(SUMOReal sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::lengthM.
Definition: MSInductLoop.h:334
std::vector< std::string > getCurrentVehicleIDs() const
Returns the ids of vehicles that have passed the detector.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
The vehicle changes lanes (micro only) XXX: What if a vehicle changes lanes and passes a junction sim...
Representation of a vehicle.
Definition: SUMOVehicle.h:66
~MSInductLoop()
Destructor.
virtual void enterDetectorByMove(SUMOVehicle &veh, SUMOReal entryTimestep)
Introduces a vehicle to the detector's map myVehiclesOnDet.
static SUMOReal speedSum(SUMOReal sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::speedM.
Definition: MSInductLoop.h:329
MSInductLoop(const std::string &id, MSLane *const lane, SUMOReal positionInMeters, const std::string &vTypes)
Constructor.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
T MIN2(T a, T b)
Definition: StdDefs.h:69
static SUMOReal passingTime(const SUMOReal lastPos, const SUMOReal passedPos, const SUMOReal currentPos, const SUMOReal lastSpeed, const SUMOReal currentSpeed)
Calculates the time at which the position passedPosition has been passed In case of a ballistic updat...
Definition: MSCFModel.cpp:367
Something on a lane to be noticed about vehicle movement.
SUMOReal getCurrentSpeed() const
Returns the speed of the vehicle on the detector.
int myEnteredVehicleNumber
The number of entered vehicles.
Definition: MSInductLoop.h:351
#define HAS_NOT_LEFT_DETECTOR
The vehicle starts or ends parking.
The vehicle has departed (was inserted into the network)
SUMOReal myLastOccupancy
Occupancy by the last vehicle detected.
Definition: MSInductLoop.h:348
virtual SUMOReal getSpeed() const =0
Returns the vehicle's current speed.
Struct to store the data of the counted vehicle internally.
Definition: MSInductLoop.h:255
bool notifyEnter(SUMOVehicle &veh, Notification reason)
Checks whether the reminder is activated by a vehicle entering the lane.
virtual void leaveDetectorByLaneChange(SUMOVehicle &veh, SUMOReal lastPos)
Removes a vehicle from the detector's map myVehiclesOnDet.
const std::string & getID() const
Returns the name of the vehicle type.
virtual SUMOReal getBackPositionOnLane(const MSLane *lane) const =0
Get the vehicle's back position along the given lane.
SUMOReal getTimestepsSinceLastDetection() const
Returns the time since the last vehicle left the detector.
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
#define SUMOReal
Definition: config.h:214
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:63
SUMOReal myLastLeaveTime
Leave-time of the last vehicle detected [s].
Definition: MSInductLoop.h:345
SUMOReal getCurrentLength() const
Returns the length of the vehicle on the detector.
virtual void leaveDetectorByMove(SUMOVehicle &veh, SUMOReal leaveTimestep)
Processes a vehicle that leaves the detector.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
virtual const std::string & getID() const =0
Get the vehicle's ID.
bool notifyLeave(SUMOVehicle &veh, SUMOReal lastPos, MSMoveReminder::Notification reason)
Dismisses the vehicle if it is on the detector due to a lane change.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
Base of value-generating classes (detectors)
The vehicle is being teleported.
bool notifyMove(SUMOVehicle &veh, SUMOReal oldPos, SUMOReal newPos, SUMOReal newSpeed)
Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle's type.