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-2017 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 #define HAS_NOT_LEFT_DETECTOR -1
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
56 MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
57  double positionInMeters,
58  const std::string& vTypes) :
59  MSMoveReminder(id, lane),
60  MSDetectorFileOutput(id, vTypes),
61  myPosition(positionInMeters),
62  myLastLeaveTime(SIMTIME),
63  myVehicleDataCont(),
64  myVehiclesOnDet() {
65  assert(myPosition >= 0 && myPosition <= myLane->getLength());
66  reset();
67 }
68 
69 
71 }
72 
73 
74 void
78  myVehicleDataCont.clear();
79 }
80 
81 
82 bool
83 MSInductLoop::notifyEnter(SUMOVehicle& veh, Notification reason, const MSLane* /* enteredLane */) {
84  if (!vehicleApplies(veh)) {
85  return false;
86  }
87  if (reason == NOTIFICATION_DEPARTED ||
88  reason == NOTIFICATION_TELEPORT ||
89  reason == NOTIFICATION_PARKING ||
90  reason == NOTIFICATION_LANE_CHANGE) {
92  myVehiclesOnDet.insert(std::make_pair(&veh, SIMTIME));
94  }
95  }
96  return true;
97 }
98 
99 
100 bool
102  double newPos, double newSpeed) {
103  if (newPos < myPosition) {
104  // detector not reached yet
105  return true;
106  }
107  const double oldSpeed = veh.getPreviousSpeed();
108  if (newPos >= myPosition && oldPos < myPosition) {
109  // entered the detector by move
110  const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
111  double entryTime = SIMTIME + timeBeforeEnter;
112  enterDetectorByMove(veh, entryTime);
113  }
114  double oldBackPos = oldPos - veh.getVehicleType().getLength();
115  double newBackPos = newPos - veh.getVehicleType().getLength();
116  if (newBackPos > myPosition) {
117  // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
118  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
119  if (oldBackPos <= myPosition) {
120  const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, newBackPos, oldSpeed, newSpeed);
121  const double leaveTime = SIMTIME + timeBeforeLeave;
122  leaveDetectorByMove(veh, leaveTime);
123  } else {
124  // vehicle is already beyond the detector...
125  // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
126  // XXX: would we need to call leaveDetectorByMove(veh, leaveTime) as it was done before
127  // I inserted this if-else differentiation? (Leo) It seems that such a call only resets
128  // the last leave Time, which seems inadequate to do for such a situation (though it actually
129  // appears in test output/e1/one_vehicle/lane_change). Moreover, if the vehicle was
130  // not removed, this call would tidy up.
131  // XXX: Indeed, we need to tidy up, e.g., in case of teleport insertion behind detector
132  // XXX: As a quickfix we just remove it. (should be discussed! Leo) Refs. #2579
133 
134  myVehiclesOnDet.erase(&veh);
135  }
136  return false;
137  }
138  // vehicle stays on the detector
139  return true;
140 }
141 
142 
143 bool
144 MSInductLoop::notifyLeave(SUMOVehicle& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
146  leaveDetectorByLaneChange(veh, lastPos);
147  return false;
148  }
149  return true;
150 }
151 
152 
153 double
155  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
156  return d.size() != 0
157  ? accumulate(d.begin(), d.end(), (double) 0.0, speedSum) / (double) d.size()
158  : -1;
159 }
160 
161 
162 double
164  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
165  return d.size() != 0
166  ? accumulate(d.begin(), d.end(), (double) 0.0, lengthSum) / (double) d.size()
167  : -1;
168 }
169 
170 
171 double
174  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
175  if (d.size() == 0) {
176  return -1;
177  }
178  double occupancy = 0;
179  double csecond = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
180  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
181  const double leaveTime = (*i).leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : (*i).leaveTimeM;
182  const double timeOnDetDuringInterval = leaveTime - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
183  occupancy += MIN2(timeOnDetDuringInterval, TS);
184  }
185  return occupancy / TS * (double) 100.;
186 }
187 
188 
189 int
191  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
192  return (int) d.size();
193 }
194 
195 
196 std::vector<std::string>
198  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
199  std::vector<std::string> ret;
200  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
201  ret.push_back((*i).idM);
202  }
203  return ret;
204 }
205 
206 
207 double
209  if (myVehiclesOnDet.size() != 0) {
210  // detector is occupied
211  return 0;
212  }
213  return SIMTIME - myLastLeaveTime;
214 }
215 
216 
217 void
219  dev.writeXMLHeader("detector", "det_e1_file.xsd");
220 }
221 
222 
223 void
225  SUMOTime startTime, SUMOTime stopTime) {
226  const double t(STEPS2TIME(stopTime - startTime));
227  const double flow = ((double)myVehicleDataCont.size() / t) * (double) 3600.0;
228  double occupancy = 0.;
229  double speedSum = 0.;
230  double lengthSum = 0.;
231  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
232  const double timeOnDetDuringInterval = i->leaveTimeM - MAX2(STEPS2TIME(startTime), i->entryTimeM);
233  occupancy += MIN2(timeOnDetDuringInterval, t);
234  speedSum += i->speedM;
235  lengthSum += i->lengthM;
236  }
237  for (std::map< SUMOVehicle*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
238  occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
239  }
240  occupancy = occupancy / t * (double) 100.;
241  const double meanSpeed = myVehicleDataCont.size() != 0 ? speedSum / (double)myVehicleDataCont.size() : -1;
242  const double meanLength = myVehicleDataCont.size() != 0 ? lengthSum / (double)myVehicleDataCont.size() : -1;
245  dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed);
246  dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
247  reset();
248 }
249 
250 
251 void
253  double entryTimestep) {
254 // // Debug (Leo)
255 // std::cout << "enterDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
256 
257  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
259 }
260 
261 
262 void
264  double leaveTimestep) {
265 
266 // // Debug (Leo)
267 // std::cout << "leaveDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
268 
269  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
270  if (it != myVehiclesOnDet.end()) {
271  double entryTimestep = it->second;
272  myVehiclesOnDet.erase(it);
273  assert(entryTimestep < leaveTimestep);
274  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
275  myLastOccupancy = leaveTimestep - entryTimestep;
276  }
277  // XXX: why is this outside the conditional block? (Leo)
278  myLastLeaveTime = leaveTimestep;
279 }
280 
281 
282 void
284 
285 // // Debug (Leo)
286 // std::cout << "leaveDetectorByLaneChange(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
287 
288  // Discard entry data
289  myVehiclesOnDet.erase(&veh);
290 }
291 
292 
293 std::vector<MSInductLoop::VehicleData>
294 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool leaveTime) const {
295  double t = STEPS2TIME(tMS);
296  std::vector<VehicleData> ret;
297  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
298  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
299  ret.push_back(*i);
300  }
301  }
302  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
303  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
304  ret.push_back(*i);
305  }
306  }
307  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
308  SUMOVehicle* v = (*i).first;
310  d.speedM = v->getSpeed();
311  ret.push_back(d);
312  }
313  return ret;
314 }
315 
316 
317 /****************************************************************************/
318 
const double myPosition
Detector&#39;s position on lane [m].
Definition: MSInductLoop.h:342
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:256
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
bool vehicleApplies(const SUMOVehicle &veh) const
Checks whether the detector measures vehicles of the given type.
The vehicle arrived at a junction.
double myLastOccupancy
Occupancy by the last vehicle detected.
Definition: MSInductLoop.h:348
MSLane *const myLane
Lane on which the reminder works.
std::vector< std::string > getCurrentVehicleIDs() const
Returns the ids of vehicles that have passed the detector.
virtual void leaveDetectorByLaneChange(SUMOVehicle &veh, double lastPos)
Removes a vehicle from the detector&#39;s map myVehiclesOnDet.
virtual void reset()
Resets all generated values to allow computation of next interval.
bool notifyLeave(SUMOVehicle &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Dismisses the vehicle if it is on the detector due to a lane change.
static double speedSum(double sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::speedM.
Definition: MSInductLoop.h:329
virtual void leaveDetectorByMove(SUMOVehicle &veh, double leaveTimestep)
Processes a vehicle that leaves the detector.
Notification
Definition of a vehicle state.
weights: time range begin
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:158
T MAX2(T a, T b)
Definition: StdDefs.h:70
SUMOTime DELTA_T
Definition: SUMOTime.cpp:40
double getCurrentLength() const
Returns the length of the vehicle on the detector.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
#define TS
Definition: SUMOTime.h:52
VehicleMap myVehiclesOnDet
Data for vehicles that have entered the detector (vehicle -> enter time)
Definition: MSInductLoop.h:369
double speedM
Speed of the vehicle in [m/s].
Definition: MSInductLoop.h:278
VehicleDataCont myLastVehicleDataCont
Data of vehicles that have completely passed the detector in the last time interval.
Definition: MSInductLoop.h:361
#define SIMTIME
Definition: SUMOTime.h:70
VehicleDataCont myVehicleDataCont
Data of vehicles that have completely passed the detector.
Definition: MSInductLoop.h:358
The vehicle changes lanes (micro only)
void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "detector" as root element.
Representation of a vehicle.
Definition: SUMOVehicle.h:67
~MSInductLoop()
Destructor.
virtual void enterDetectorByMove(SUMOVehicle &veh, double entryTimestep)
Introduces a vehicle to the detector&#39;s map myVehiclesOnDet.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >())
Writes an XML header with optional configuration.
double getCurrentSpeed() const
Returns the speed of the vehicle on the detector.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:257
T MIN2(T a, T b)
Definition: StdDefs.h:64
Something on a lane to be noticed about vehicle movement.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
double getTimeSinceLastDetection() const
Returns the time since the last vehicle left the detector.
MSInductLoop(const std::string &id, MSLane *const lane, double positionInMeters, const std::string &vTypes)
Constructor.
int myEnteredVehicleNumber
The number of entered vehicles.
Definition: MSInductLoop.h:351
#define HAS_NOT_LEFT_DETECTOR
bool notifyEnter(SUMOVehicle &veh, Notification reason, const MSLane *enteredLane=0)
Checks whether the reminder is activated by a vehicle entering the lane.
int getCurrentPassedNumber() const
Returns the number of vehicles that have passed the detector.
static double passingTime(const double lastPos, const double passedPos, const double currentPos, const double lastSpeed, const double currentSpeed)
Calculates the time at which the position passedPosition has been passed In case of a ballistic updat...
Definition: MSCFModel.cpp:372
virtual double getBackPositionOnLane(const MSLane *lane) const =0
Get the vehicle&#39;s back position along the given lane.
The vehicle starts or ends parking.
The vehicle has departed (was inserted into the network)
Struct to store the data of the counted vehicle internally.
Definition: MSInductLoop.h:255
virtual double getPositionOnLane() const =0
Get the vehicle&#39;s position along the lane.
weights: time range end
const std::string & getID() const
Returns the name of the vehicle type.
bool notifyMove(SUMOVehicle &veh, double oldPos, double newPos, double newSpeed)
Checks whether the vehicle shall be counted and/or shall still touch this MSMoveReminder.
double getLength() const
Get vehicle&#39;s length [m].
an aggreagated-output interval
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:71
bool closeTag()
Closes the most recently opened tag.
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:63
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...
long long int SUMOTime
Definition: TraCIDefs.h:52
double getCurrentOccupancy() const
Returns the current occupancy.
double myLastLeaveTime
Leave-time of the last vehicle detected [s].
Definition: MSInductLoop.h:345
virtual double getSpeed() const =0
Returns the vehicle&#39;s current speed.
Representation of a lane in the micro simulation.
Definition: MSLane.h:79
static double lengthSum(double sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::lengthM.
Definition: MSInductLoop.h:334
virtual double getPreviousSpeed() const =0
Returns the vehicle&#39;s previous speed.
virtual const std::string & getID() const =0
Get the vehicle&#39;s ID.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
Base of value-generating classes (detectors)
The vehicle is being teleported.
virtual const MSVehicleType & getVehicleType() const =0
Returns the vehicle&#39;s type.