SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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.sourceforge.net/
15 // Copyright (C) 2001-2012 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 
56 // ===========================================================================
57 // method definitions
58 // ===========================================================================
59 MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
60  SUMOReal positionInMeters, bool splitByType) :
61  MSMoveReminder(lane),
63  myPosition(positionInMeters),
64  myLastLeaveTime(0),
65  myVehicleDataCont(),
66  myVehiclesOnDet(), mySplitByType(splitByType) {
67  assert(myPosition >= 0 && myPosition <= myLane->getLength());
68  reset();
69  myLastLeaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
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 && oldPos - veh.getVehicleType().getLength() <= myPosition) {
103  // vehicle passed the detector
104  SUMOReal leaveTime = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
105  leaveTime += (myPosition - oldPos + veh.getVehicleType().getLength()) / newSpeed;
106  leaveDetectorByMove(veh, leaveTime);
107  return false;
108  }
109  // vehicle stays on the detector
110  return true;
111 }
112 
113 
114 bool
117  // vehicle is on detector during lane change or arrival, or ...
119  return false;
120  }
121  return true;
122 }
123 
124 
125 bool
127  if (veh.getPositionOnLane() - veh.getVehicleType().getLength() > myPosition) {
128  // vehicle-front is beyond detector. Ignore
129  return false;
130  }
131  // vehicle is in front of detector
132  return true;
133 }
134 
135 
136 SUMOReal
138  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
139  return d.size() != 0
140  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) d.size()
141  : -1;
142 }
143 
144 
145 SUMOReal
147  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
148  return d.size() != 0
149  ? accumulate(d.begin(), d.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) d.size()
150  : -1;
151 }
152 
153 
154 SUMOReal
157  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
158  if (d.size() == 0) {
159  return -1;
160  }
161  SUMOReal occupancy = 0;
162  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
163  SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
164  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, TS);
165  occupancy += timeOnDetDuringInterval;
166  }
167  return occupancy / TS * (SUMOReal) 100.;
168 }
169 
170 
171 unsigned int
173  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
174  return (unsigned int) d.size();
175 }
176 
177 
178 std::vector<std::string>
180  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
181  std::vector<std::string> ret;
182  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
183  ret.push_back((*i).idM);
184  }
185  return ret;
186 }
187 
188 
189 SUMOReal
191  if (myVehiclesOnDet.size() != 0) {
192  // detector is occupied
193  return 0;
194  }
195  return STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep()) - myLastLeaveTime;
196 }
197 
198 
199 void
201  dev.writeXMLHeader("detector");
202 }
203 
204 
205 void
207  SUMOTime startTime, SUMOTime stopTime) {
208  writeTypedXMLOutput(dev, startTime, stopTime, "", myVehicleDataCont, myVehiclesOnDet);
209  if (mySplitByType) {
210  dev << ">\n";
211  std::map<std::string, std::pair<VehicleDataCont, VehicleMap> > types;
212  // collect / divide
213  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
214  if (types.find((*i).typeIDM) == types.end()) {
215  types[(*i).typeIDM] = make_pair(VehicleDataCont(), VehicleMap());
216  }
217  types[(*i).typeIDM].first.push_back(*i);
218  }
219  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
220  const std::string& type = (*i).first->getVehicleType().getID();
221  if (types.find(type) == types.end()) {
222  types[type] = make_pair(VehicleDataCont(), VehicleMap());
223  }
224  types[type].second[(*i).first] = (*i).second;
225  }
226  // write
227  for (std::map<std::string, std::pair<VehicleDataCont, VehicleMap> >::const_iterator i = types.begin(); i != types.end(); ++i) {
228  writeTypedXMLOutput(dev, startTime, stopTime, (*i).first, (*i).second.first, (*i).second.second);
229  dev << "/>\n";
230  }
231  dev << " </interval>\n";
232  } else {
233  dev << "/>\n";
234  }
235  reset();
236 }
237 
238 void
240  const std::string& type, const VehicleDataCont& vdc, const VehicleMap& vm) {
241  SUMOReal t(STEPS2TIME(stopTime - startTime));
242  unsigned nVehCrossed = (unsigned) vdc.size();
243  if (type == "") {
244  nVehCrossed += myDismissedVehicleNumber;
245  }
246  SUMOReal flow = ((SUMOReal) vdc.size() / (SUMOReal) t) * (SUMOReal) 3600.0;
247  SUMOReal occupancy = 0;
248  for (std::deque< VehicleData >::const_iterator i = vdc.begin(); i != vdc.end(); ++i) {
249  SUMOReal timeOnDetDuringInterval = (*i).leaveTimeM - MAX2(STEPS2TIME(startTime), (*i).entryTimeM);
250  timeOnDetDuringInterval = MIN2(timeOnDetDuringInterval, t);
251  occupancy += timeOnDetDuringInterval;
252  }
253  for (std::map< SUMOVehicle*, SUMOReal >::const_iterator i = vm.begin(); i != vm.end(); ++i) {
254  SUMOReal timeOnDetDuringInterval = STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), (*i).second);
255  occupancy += timeOnDetDuringInterval;
256  }
257  occupancy = occupancy / t * (SUMOReal) 100.;
258  SUMOReal meanSpeed = vdc.size() != 0
259  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, speedSum) / (SUMOReal) vdc.size()
260  : -1;
261  SUMOReal meanLength = vdc.size() != 0
262  ? accumulate(vdc.begin(), vdc.end(), (SUMOReal) 0.0, lengthSum) / (SUMOReal) vdc.size()
263  : -1;
264  if (type != "") {
265  dev << " <typedInterval type=\"" + type + "\" ";
266  } else {
267  dev << " <interval ";
268  }
269  dev << "begin=\"" << time2string(startTime) << "\" end=\"" <<
270  time2string(stopTime) << "\" " << "id=\"" << StringUtils::escapeXML(getID()) << "\" ";
271  dev << "nVehContrib=\"" << vdc.size() << "\" flow=\"" << flow <<
272  "\" occupancy=\"" << occupancy << "\" speed=\"" << meanSpeed <<
273  "\" length=\"" << meanLength <<
274  "\" nVehEntered=\"" << nVehCrossed << "\"";
275 }
276 
277 
278 void
280  SUMOReal entryTimestep) {
281  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
282 }
283 
284 
285 void
287  SUMOReal leaveTimestep) {
288  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
289  if (it != myVehiclesOnDet.end()) {
290  SUMOReal entryTimestep = it->second;
291  myVehiclesOnDet.erase(it);
292  assert(entryTimestep < leaveTimestep);
293  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
294  myLastOccupancy = leaveTimestep - entryTimestep;
295  }
296  myLastLeaveTime = leaveTimestep;
297 }
298 
299 
300 void
302  // Discard entry data
303  myVehiclesOnDet.erase(&veh);
305 }
306 
307 
308 std::vector<MSInductLoop::VehicleData>
310  SUMOReal t = STEPS2TIME(tMS);
311  std::vector<VehicleData> ret;
312  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
313  if ((*i).leaveTimeM >= t) {
314  ret.push_back(*i);
315  }
316  }
317  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
318  if ((*i).leaveTimeM >= t) {
319  ret.push_back(*i);
320  }
321  }
323  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
324  SUMOVehicle* v = (*i).first;
325  VehicleData d(v->getID(), v->getVehicleType().getLength(), (*i).second, STEPS2TIME(ct), v->getVehicleType().getID());
326  d.speedM = v->getSpeed();
327  ret.push_back(d);
328  }
329  return ret;
330 }
331 
332 
333 /****************************************************************************/
334