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-2015 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  SUMOReal newPos, SUMOReal newSpeed) {
88  if (newPos < myPosition) {
89  // detector not reached yet
90  return true;
91  }
92  if (newPos >= myPosition && oldPos < myPosition) {
93  // entered the detector by move
94  SUMOReal entryTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
95  if (newSpeed != 0) {
96  if (myPosition > oldPos) {
97  entryTime += (myPosition - oldPos) / newSpeed;
98  }
99  }
100  enterDetectorByMove(veh, entryTime);
101  }
102  if (newPos - veh.getVehicleType().getLength() > myPosition) {
103  // vehicle passed the detector (it may have changed onto this lane
104  // somewhere past the detector)
105  assert(newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
106  SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
107  if (newSpeed > 0) {
108  leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
109  }
110  leaveDetectorByMove(veh, leaveTime);
111  return false;
112  }
113  // vehicle stays on the detector
114  return true;
115 }
116 
117 
118 bool
121  leaveDetectorByLaneChange(veh, lastPos);
122  return false;
123  }
124  return true;
125 }
126 
127 
128 SUMOReal
130  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
131  return d.size() != 0
132  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
133  : -1;
134 }
135 
136 
137 SUMOReal
139  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
140  return d.size() != 0
141  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
142  : -1;
143 }
144 
145 
146 SUMOReal
149  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
150  if (d.size() == 0) {
151  return -1;
152  }
153  SUMOReal occupancy = 0;
154  SUMOReal csecond = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
155  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
156  const SUMOReal leaveTime = (*i).leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : (*i).leaveTimeM;
157  SUMOReal timeOnDetDuringInterval = leaveTime - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
158  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
159  occupancy += timeOnDetDuringInterval;
160  }
161  return occupancy / TS * (SUMOReal) 100.;
162 }
163 
164 
165 unsigned int
167  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
168  return (unsigned int) d.size();
169 }
170 
171 
172 std::vector<std::string>
174  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
175  std::vector<std::string> ret;
176  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
177  ret.push_back((*i).idM);
178  }
179  return ret;
180 }
181 
182 
183 SUMOReal
185  if (myVehiclesOnDet.size() != 0) {
186  // detector is occupied
187  return 0;
188  }
189  return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
190 }
191 
192 
193 void
195  dev.writeXMLHeader("detector", "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.dlr.de/xsd/det_e1_file.xsd\"");
196 }
197 
198 
199 void
201  SUMOTime startTime, SUMOTime stopTime) {
202  writeTypedXMLOutput(dev, startTime, stopTime, "", myVehicleDataCont, myVehiclesOnDet);
203  if (mySplitByType) {
204  dev << ">\n";
205  std::map<std::string, std::pair<VehicleDataCont, VehicleMap> > types;
206  // collect / divide
207  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
208  if (types.find((*i).typeIDM) == types.end()) {
209  types[(*i).typeIDM] = make_pair(VehicleDataCont(), VehicleMap());
210  }
211  types[(*i).typeIDM].first.push_back(*i);
212  }
213  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
214  const std::string& type = (*i).first->getVehicleType().getID();
215  if (types.find(type) == types.end()) {
216  types[type] = make_pair(VehicleDataCont(), VehicleMap());
217  }
218  types[type].second[(*i).first] = (*i).second;
219  }
220  // write
221  for (std::map<std::string, std::pair<VehicleDataCont, VehicleMap> >::const_iterator i = types.begin(); i != types.end(); ++i) {
222  writeTypedXMLOutput(dev, startTime, stopTime, (*i).first, (*i).second.first, (*i).second.second);
223  dev << "/>\n";
224  }
225  dev << " </interval>\n";
226  } else {
227  dev << "/>\n";
228  }
229  reset();
230 }
231 
232 void
234  const std::string& type, const VehicleDataCont& vdc, const VehicleMap& vm) {
235  SUMOReal t(STEPS2TIME(stopTime - startTime));
236  unsigned nVehCrossed = (unsigned) vdc.size();
237  if (type == "") {
238  nVehCrossed += myDismissedVehicleNumber;
239  }
240  SUMOReal flow = ((SUMOReal) vdc.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
241  SUMOReal occupancy = 0;
242  for (std::deque< VehicleData >::const_iterator i = vdc.begin(); i != vdc.end(); ++i) {
243  SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
244  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
245  occupancy += timeOnDetDuringInterval;
246  }
247  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = vm.begin(); i != vm.end(); ++i) {
248  SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
249  occupancy += timeOnDetDuringInterval;
250  }
251  occupancy = occupancy / t * (SUMOReal) 100.;
252  SUMOReal meanSpeed = vdc.size() != 0
253  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) vdc.size()
254  : -1;
255  SUMOReal meanLength = vdc.size() != 0
256  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) vdc.size()
257  : -1;
258  if (type != "") {
259  dev << " <typedInterval type=\"" + type + "\" ";
260  } else {
261  dev << " <interval ";
262  }
263  dev << "begin=\"" << time2string(startTime) << "\" end=\"" <<
264  time2string(stopTime) << "\" " << "id=\"" << StringUtils::escapeXML(getID()) << "\" ";
265  dev << "nVehContrib=\"" << vdc.size() << "\" flow=\"" << flow <<
266  "\" occupancy=\"" << occupancy << "\" speed=\"" << meanSpeed <<
267  "\" length=\"" << meanLength <<
268  "\" nVehEntered=\"" << nVehCrossed << "\"";
269 }
270 
271 
272 void
274  SUMOReal entryTimestep) {
275  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
276 }
277 
278 
279 void
281  SUMOReal leaveTimestep) {
282  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
283  if (it != myVehiclesOnDet.end()) {
284  SUMOReal entryTimestep = it->second;
285  myVehiclesOnDet.erase(it);
286  assert(entryTimestep < leaveTimestep);
287  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
288  myLastOccupancy = leaveTimestep - entryTimestep;
289  }
290  myLastLeaveTime = leaveTimestep;
291 }
292 
293 
294 void
296  // Discard entry data
297  myVehiclesOnDet.erase(&veh);
298  if (lastPos > myPosition) {
299  // vehicle is on detector during lane change or arrival, or ...
301  }
302 }
303 
304 
305 std::vector<MSInductLoop::VehicleData>
307  SUMOReal t = STEPS2TIME(tMS);
308  std::vector<VehicleData> ret;
309  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
310  if ((*i).leaveTimeM >= t) {
311  ret.push_back(*i);
312  }
313  }
314  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
315  if ((*i).leaveTimeM >= t) {
316  ret.push_back(*i);
317  }
318  }
319  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
320  SUMOVehicle* v = (*i).first;
322  d.speedM = v->getSpeed();
323  ret.push_back(d);
324  }
325  return ret;
326 }
327 
328 
329 /****************************************************************************/
330 
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
unsigned myDismissedVehicleNumber
The number of dismissed vehicles.
Definition: MSInductLoop.h:340
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:61
SUMOReal getLength() const
Get vehicle&#39;s length [m].
virtual std::vector< VehicleData > collectVehiclesOnDet(SUMOTime t) const
Returns vehicle data for vehicles that have been on the detector starting at the given time...
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:162
T MAX2(T a, T b)
Definition: StdDefs.h:79
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:357
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:255
VehicleDataCont myLastVehicleDataCont
Data of vehicles that have completely passed the detector in the last time interval.
Definition: MSInductLoop.h:350
const SUMOReal myPosition
Detector&#39;s position on lane [m].
Definition: MSInductLoop.h:328
The simulated network and simulation perfomer.
Definition: MSNet.h:94
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:347
SUMOReal speedM
Speed of the vehicle in [m/s].
Definition: MSInductLoop.h:266
std::deque< VehicleData > VehicleDataCont
Type of myVehicleDataCont.
Definition: MSInductLoop.h:344
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:320
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:65
Representation of a vehicle.
Definition: SUMOVehicle.h:65
~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:315
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
bool mySplitByType
Whether additional information split by vehicle classes shall be generated.
Definition: MSInductLoop.h:331
T MIN2(T a, T b)
Definition: StdDefs.h:73
Something on a lane to be noticed about vehicle movement.
SUMOReal getCurrentSpeed() const
Returns the speed of the vehicle on the detector.
unsigned int getCurrentPassedNumber() const
Returns the number of vehicles that have passed the detector.
#define HAS_NOT_LEFT_DETECTOR
SUMOReal myLastOccupancy
Occupancy by the last vehicle detected.
Definition: MSInductLoop.h:337
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:243
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:214
SUMOReal myLastLeaveTime
Leave-time of the last vehicle detected [s].
Definition: MSInductLoop.h:334
void writeTypedXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime, const std::string &type, const VehicleDataCont &vdc, const VehicleMap &vm)
#define DELTA_T
Definition: SUMOTime.h:50
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:77
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:354
Base of value-generating classes (detectors)
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.