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 SUMOReal getPositionOnLane() const =0
Get the vehicle&#39;s position along the lane.
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)
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
#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.
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
virtual SUMOReal getSpeed() const =0
Returns the vehicle&#39;s current speed.
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.
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:213
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
virtual const std::string & getID() const =0
Get the vehicle&#39;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.
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.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.