SUMO - Simulation of Urban MObility
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, bool splitByType) :
62  MSMoveReminder(id, lane),
64  myPosition(positionInMeters), mySplitByType(splitByType),
65  myLastLeaveTime(STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())),
66  myVehicleDataCont(),
67  myVehiclesOnDet() {
68  assert(myPosition >= 0 && myPosition <= myLane->getLength());
69  reset();
70 }
71 
72 
74 }
75 
76 
77 void
81  myVehicleDataCont.clear();
82 }
83 
84 
85 bool
87  if (reason == NOTIFICATION_DEPARTED ||
88  reason == NOTIFICATION_TELEPORT ||
89  reason == NOTIFICATION_PARKING ||
90  reason == NOTIFICATION_LANE_CHANGE) {
91  const SUMOReal front = veh.getPositionOnLane();
92  const SUMOReal back = front - veh.getVehicleType().getLength();
93  if (front >= myPosition && back < myPosition) {
94  myVehiclesOnDet.insert(std::make_pair(&veh, STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep())));
95  }
96  }
97  return true;
98 }
99 
100 
101 bool
103  SUMOReal newPos, SUMOReal newSpeed) {
104  if (newPos < myPosition) {
105  // detector not reached yet
106  return true;
107  }
108  if (newPos >= myPosition && oldPos < myPosition) {
109  // entered the detector by move
110  SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
111  if (newSpeed != 0) {
112  if (myPosition > oldPos) {
113  entryTime += (myPosition - oldPos) / newSpeed;
114  }
115  }
116  enterDetectorByMove(veh, entryTime);
117  }
118  if (newPos - veh.getVehicleType().getLength() > myPosition) {
119  // vehicle passed the detector (it may have changed onto this lane
120  // somewhere past the detector)
121  assert(newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
122  SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
123  if (newSpeed > 0) {
124  leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
125  }
126  leaveDetectorByMove(veh, leaveTime);
127  return false;
128  }
129  // vehicle stays on the detector
130  return true;
131 }
132 
133 
134 bool
137  leaveDetectorByLaneChange(veh, lastPos);
138  return false;
139  }
140  return true;
141 }
142 
143 
144 SUMOReal
146  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
147  return d.size() != 0
148  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
149  : -1;
150 }
151 
152 
153 SUMOReal
155  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
156  return d.size() != 0
157  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
158  : -1;
159 }
160 
161 
162 SUMOReal
165  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
166  if (d.size() == 0) {
167  return -1;
168  }
169  SUMOReal occupancy = 0;
170  SUMOReal csecond = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
171  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
172  const SUMOReal leaveTime = (*i).leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : (*i).leaveTimeM;
173  SUMOReal timeOnDetDuringInterval = leaveTime - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
174  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
175  occupancy += timeOnDetDuringInterval;
176  }
177  return occupancy / TS * (SUMOReal) 100.;
178 }
179 
180 
181 int
183  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
184  return (int) d.size();
185 }
186 
187 
188 std::vector<std::string>
190  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
191  std::vector<std::string> ret;
192  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
193  ret.push_back((*i).idM);
194  }
195  return ret;
196 }
197 
198 
199 SUMOReal
201  if (myVehiclesOnDet.size() != 0) {
202  // detector is occupied
203  return 0;
204  }
205  return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
206 }
207 
208 
209 void
211  dev.writeXMLHeader("detector", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/det_e1_file.xsd\"");
212 }
213 
214 
215 void
217  SUMOTime startTime, SUMOTime stopTime) {
218  writeTypedXMLOutput(dev, startTime, stopTime, "", myVehicleDataCont, myVehiclesOnDet);
219  if (mySplitByType) {
220  dev << ">\n";
221  std::map<std::string, std::pair<VehicleDataCont, VehicleMap> > types;
222  // collect / divide
223  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
224  if (types.find((*i).typeIDM) == types.end()) {
225  types[(*i).typeIDM] = make_pair(VehicleDataCont(), VehicleMap());
226  }
227  types[(*i).typeIDM].first.push_back(*i);
228  }
229  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
230  const std::string& type = (*i).first->getVehicleType().getID();
231  if (types.find(type) == types.end()) {
232  types[type] = make_pair(VehicleDataCont(), VehicleMap());
233  }
234  types[type].second[(*i).first] = (*i).second;
235  }
236  // write
237  for (std::map<std::string, std::pair<VehicleDataCont, VehicleMap> >::const_iterator i = types.begin(); i != types.end(); ++i) {
238  writeTypedXMLOutput(dev, startTime, stopTime, (*i).first, (*i).second.first, (*i).second.second);
239  dev << "/>\n";
240  }
241  dev << " </interval>\n";
242  } else {
243  dev << "/>\n";
244  }
245  reset();
246 }
247 
248 void
250  const std::string& type, const VehicleDataCont& vdc, const VehicleMap& vm) {
251  SUMOReal t(STEPS2TIME(stopTime - startTime));
252  int nVehCrossed = (int) vdc.size();
253  if (type == "") {
254  nVehCrossed += myDismissedVehicleNumber;
255  }
256  SUMOReal flow = ((SUMOReal) vdc.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
257  SUMOReal occupancy = 0;
258  for (std::deque< VehicleData >::const_iterator i = vdc.begin(); i != vdc.end(); ++i) {
259  SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
260  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
261  occupancy += timeOnDetDuringInterval;
262  }
263  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = vm.begin(); i != vm.end(); ++i) {
264  SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
265  occupancy += timeOnDetDuringInterval;
266  }
267  occupancy = occupancy / t * (SUMOReal) 100.;
268  SUMOReal meanSpeed = vdc.size() != 0
269  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) vdc.size()
270  : -1;
271  SUMOReal meanLength = vdc.size() != 0
272  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) vdc.size()
273  : -1;
274  if (type != "") {
275  dev << " <typedInterval type=\"" + type + "\" ";
276  } else {
277  dev << " <interval ";
278  }
279  dev << "begin=\"" << time2string(startTime) << "\" end=\"" <<
280  time2string(stopTime) << "\" " << "id=\"" << StringUtils::escapeXML(getID()) << "\" ";
281  dev << "nVehContrib=\"" << vdc.size() << "\" flow=\"" << flow <<
282  "\" occupancy=\"" << occupancy << "\" speed=\"" << meanSpeed <<
283  "\" length=\"" << meanLength <<
284  "\" nVehEntered=\"" << nVehCrossed << "\"";
285 }
286 
287 
288 void
290  SUMOReal entryTimestep) {
291  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
292 }
293 
294 
295 void
297  SUMOReal leaveTimestep) {
298  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
299  if (it != myVehiclesOnDet.end()) {
300  SUMOReal entryTimestep = it->second;
301  myVehiclesOnDet.erase(it);
302  assert(entryTimestep < leaveTimestep);
303  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
304  myLastOccupancy = leaveTimestep - entryTimestep;
305  }
306  myLastLeaveTime = leaveTimestep;
307 }
308 
309 
310 void
312  // Discard entry data
313  myVehiclesOnDet.erase(&veh);
314  if (lastPos > myPosition) {
315  // vehicle is on detector during lane change or arrival, or ...
317  }
318 }
319 
320 
321 std::vector<MSInductLoop::VehicleData>
322 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool leaveTime) const {
323  SUMOReal t = STEPS2TIME(tMS);
324  std::vector<VehicleData> ret;
325  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
326  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
327  ret.push_back(*i);
328  }
329  }
330  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
331  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
332  ret.push_back(*i);
333  }
334  }
335  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
336  SUMOVehicle* v = (*i).first;
338  d.speedM = v->getSpeed();
339  ret.push_back(d);
340  }
341  return ret;
342 }
343 
344 
345 /****************************************************************************/
346 
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
long long int SUMOTime
Definition: SUMOTime.h:43
MSInductLoop(const std::string &id, MSLane *const lane, SUMOReal positionInMeters, bool splitByType)
Constructor.
The vehicle arrived at a junction.
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.
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
SUMOReal getLength() const
Get vehicle&#39;s length [m].
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:370
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:363
const SUMOReal myPosition
Detector&#39;s position on lane [m].
Definition: MSInductLoop.h:341
The simulated network and simulation perfomer.
Definition: MSNet.h:93
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:360
SUMOReal speedM
Speed of the vehicle in [m/s].
Definition: MSInductLoop.h:277
std::deque< VehicleData > VehicleDataCont
Type of myVehicleDataCont.
Definition: MSInductLoop.h:357
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:333
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)
virtual SUMOReal getPositionOnLane() const =0
Get the vehicle&#39;s position along the lane.
Representation of a vehicle.
Definition: SUMOVehicle.h:66
~MSInductLoop()
Destructor.
virtual void enterDetectorByMove(SUMOVehicle &veh, SUMOReal entryTimestep)
Introduces a vehicle to the detector&#39;s map myVehiclesOnDet.
static SUMOReal speedSum(SUMOReal sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::speedM.
Definition: MSInductLoop.h:328
virtual SUMOReal getSpeed() const =0
Returns the vehicle&#39;s current speed.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
bool mySplitByType
Whether additional information split by vehicle classes shall be generated.
Definition: MSInductLoop.h:344
T MIN2(T a, T b)
Definition: StdDefs.h:69
Something on a lane to be noticed about vehicle movement.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.
SUMOReal getCurrentSpeed() const
Returns the speed of the vehicle on the detector.
#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:350
Struct to store the data of the counted vehicle internally.
Definition: MSInductLoop.h:254
int myDismissedVehicleNumber
The number of dismissed vehicles.
Definition: MSInductLoop.h:353
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&#39;s map myVehiclesOnDet.
const std::string & getID() const
Returns the name of the vehicle type.
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
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
#define SUMOReal
Definition: config.h:214
SUMOReal myLastLeaveTime
Leave-time of the last vehicle detected [s].
Definition: MSInductLoop.h:347
void writeTypedXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime, const std::string &type, const VehicleDataCont &vdc, const VehicleMap &vm)
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
bool notifyLeave(SUMOVehicle &veh, SUMOReal lastPos, MSMoveReminder::Notification reason)
Dismisses the vehicle if it is on the detector due to a lane change.
std::map< SUMOVehicle *, SUMOReal > VehicleMap
Type of myVehiclesOnDet.
Definition: MSInductLoop.h:367
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.