SUMO - Simulation of Urban MObility
MSInductLoop.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
22 // An unextended detector measuring at a fixed position on a fixed lane.
23 /****************************************************************************/
24 
25 
26 // ===========================================================================
27 // included modules
28 // ===========================================================================
29 #ifdef _MSC_VER
30 #include <windows_config.h>
31 #else
32 #include <config.h>
33 #endif
34 
35 #include "MSInductLoop.h"
36 #include <cassert>
37 #include <numeric>
38 #include <utility>
40 #include <utils/common/ToString.h>
42 #include <microsim/MSLane.h>
43 #include <microsim/MSVehicle.h>
44 #include <microsim/MSNet.h>
49 
50 #define HAS_NOT_LEFT_DETECTOR -1
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 MSInductLoop::MSInductLoop(const std::string& id, MSLane* const lane,
56  double positionInMeters,
57  const std::string& vTypes) :
58  MSMoveReminder(id, lane),
59  MSDetectorFileOutput(id, vTypes),
60  myPosition(positionInMeters),
61  myLastLeaveTime(SIMTIME),
62  myVehicleDataCont(),
63  myVehiclesOnDet() {
64  assert(myPosition >= 0 && myPosition <= myLane->getLength());
65  reset();
66 }
67 
68 
70 }
71 
72 
73 void
77  myVehicleDataCont.clear();
78 }
79 
80 
81 bool
82 MSInductLoop::notifyEnter(SUMOVehicle& veh, Notification reason, const MSLane* /* enteredLane */) {
83  if (!vehicleApplies(veh)) {
84  return false;
85  }
86  if (reason == NOTIFICATION_DEPARTED ||
87  reason == NOTIFICATION_TELEPORT ||
88  reason == NOTIFICATION_PARKING ||
89  reason == NOTIFICATION_LANE_CHANGE) {
91  myVehiclesOnDet.insert(std::make_pair(&veh, SIMTIME));
93  }
94  }
95  return true;
96 }
97 
98 
99 bool
101  double newPos, double newSpeed) {
102  if (newPos < myPosition) {
103  // detector not reached yet
104  return true;
105  }
106  const double oldSpeed = veh.getPreviousSpeed();
107  if (newPos >= myPosition && oldPos < myPosition) {
108  // entered the detector by move
109  const double timeBeforeEnter = MSCFModel::passingTime(oldPos, myPosition, newPos, oldSpeed, newSpeed);
110  double entryTime = SIMTIME + timeBeforeEnter;
111  enterDetectorByMove(veh, entryTime);
112  }
113  double oldBackPos = oldPos - veh.getVehicleType().getLength();
114  double newBackPos = newPos - veh.getVehicleType().getLength();
115  if (newBackPos > myPosition) {
116  // vehicle passed the detector (it may have changed onto this lane somewhere past the detector)
117  assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed > 0 || myVehiclesOnDet.find(&veh) == myVehiclesOnDet.end());
118  if (oldBackPos <= myPosition) {
119  const double timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myPosition, newBackPos, oldSpeed, newSpeed);
120  const double leaveTime = SIMTIME + timeBeforeLeave;
121  leaveDetectorByMove(veh, leaveTime);
122  } else {
123  // vehicle is already beyond the detector...
124  // This can happen even if it is still registered in myVehiclesOnDet, e.g., after teleport.
125  // XXX: would we need to call leaveDetectorByMove(veh, leaveTime) as it was done before
126  // I inserted this if-else differentiation? (Leo) It seems that such a call only resets
127  // the last leave Time, which seems inadequate to do for such a situation (though it actually
128  // appears in test output/e1/one_vehicle/lane_change). Moreover, if the vehicle was
129  // not removed, this call would tidy up.
130  // XXX: Indeed, we need to tidy up, e.g., in case of teleport insertion behind detector
131  // XXX: As a quickfix we just remove it. (should be discussed! Leo) Refs. #2579
132 
133  myVehiclesOnDet.erase(&veh);
134  }
135  return false;
136  }
137  // vehicle stays on the detector
138  return true;
139 }
140 
141 
142 bool
143 MSInductLoop::notifyLeave(SUMOVehicle& veh, double lastPos, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
145  leaveDetectorByLaneChange(veh, lastPos);
146  return false;
147  }
148  return true;
149 }
150 
151 
152 double
154  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
155  return d.size() != 0
156  ? accumulate(d.begin(), d.end(), (double) 0.0, speedSum) / (double) d.size()
157  : -1;
158 }
159 
160 
161 double
163  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
164  return d.size() != 0
165  ? accumulate(d.begin(), d.end(), (double) 0.0, lengthSum) / (double) d.size()
166  : -1;
167 }
168 
169 
170 double
173  std::vector<VehicleData> d = collectVehiclesOnDet(tbeg);
174  if (d.size() == 0) {
175  return -1;
176  }
177  double occupancy = 0;
178  double csecond = STEPS2TIME(MSNet::getInstance()->getCurrentTimeStep());
179  for (std::vector< VehicleData >::const_iterator i = d.begin(); i != d.end(); ++i) {
180  const double leaveTime = (*i).leaveTimeM == HAS_NOT_LEFT_DETECTOR ? csecond : (*i).leaveTimeM;
181  const double timeOnDetDuringInterval = leaveTime - MAX2(STEPS2TIME(tbeg), (*i).entryTimeM);
182  occupancy += MIN2(timeOnDetDuringInterval, TS);
183  }
184  return occupancy / TS * (double) 100.;
185 }
186 
187 
188 int
190  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
191  return (int) d.size();
192 }
193 
194 
195 std::vector<std::string>
197  std::vector<VehicleData> d = collectVehiclesOnDet(MSNet::getInstance()->getCurrentTimeStep() - DELTA_T);
198  std::vector<std::string> ret;
199  for (std::vector<VehicleData>::iterator i = d.begin(); i != d.end(); ++i) {
200  ret.push_back((*i).idM);
201  }
202  return ret;
203 }
204 
205 
206 double
208  if (myVehiclesOnDet.size() != 0) {
209  // detector is occupied
210  return 0;
211  }
212  return SIMTIME - myLastLeaveTime;
213 }
214 
215 
216 void
218  dev.writeXMLHeader("detector", "det_e1_file.xsd");
219 }
220 
221 
222 void
224  SUMOTime startTime, SUMOTime stopTime) {
225  const double t(STEPS2TIME(stopTime - startTime));
226  const double flow = ((double)myVehicleDataCont.size() / t) * (double) 3600.0;
227  double occupancy = 0.;
228  double speedSum = 0.;
229  double lengthSum = 0.;
230  for (std::deque< VehicleData >::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
231  const double timeOnDetDuringInterval = i->leaveTimeM - MAX2(STEPS2TIME(startTime), i->entryTimeM);
232  occupancy += MIN2(timeOnDetDuringInterval, t);
233  speedSum += i->speedM;
234  lengthSum += i->lengthM;
235  }
236  for (std::map< SUMOVehicle*, double >::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
237  occupancy += STEPS2TIME(stopTime) - MAX2(STEPS2TIME(startTime), i->second);
238  }
239  occupancy = occupancy / t * (double) 100.;
240  const double meanSpeed = myVehicleDataCont.size() != 0 ? speedSum / (double)myVehicleDataCont.size() : -1;
241  const double meanLength = myVehicleDataCont.size() != 0 ? lengthSum / (double)myVehicleDataCont.size() : -1;
244  dev.writeAttr("flow", flow).writeAttr("occupancy", occupancy).writeAttr("speed", meanSpeed);
245  dev.writeAttr("length", meanLength).writeAttr("nVehEntered", myEnteredVehicleNumber).closeTag();
246  reset();
247 }
248 
249 
250 void
252  double entryTimestep) {
253 // // Debug (Leo)
254 // std::cout << "enterDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
255 
256  myVehiclesOnDet.insert(std::make_pair(&veh, entryTimestep));
258 }
259 
260 
261 void
263  double leaveTimestep) {
264 
265 // // Debug (Leo)
266 // std::cout << "leaveDetectorByMove(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
267 
268  VehicleMap::iterator it = myVehiclesOnDet.find(&veh);
269  if (it != myVehiclesOnDet.end()) {
270  double entryTimestep = it->second;
271  myVehiclesOnDet.erase(it);
272  assert(entryTimestep < leaveTimestep);
273  myVehicleDataCont.push_back(VehicleData(veh.getID(), veh.getVehicleType().getLength(), entryTimestep, leaveTimestep, veh.getVehicleType().getID()));
274  myLastOccupancy = leaveTimestep - entryTimestep;
275  }
276  // XXX: why is this outside the conditional block? (Leo)
277  myLastLeaveTime = leaveTimestep;
278 }
279 
280 
281 void
283 
284 // // Debug (Leo)
285 // std::cout << "leaveDetectorByLaneChange(), detector = '"<< myID <<"', veh = '" << veh.getID() << "'\n";
286 
287  // Discard entry data
288  myVehiclesOnDet.erase(&veh);
289 }
290 
291 
292 std::vector<MSInductLoop::VehicleData>
293 MSInductLoop::collectVehiclesOnDet(SUMOTime tMS, bool leaveTime) const {
294  double t = STEPS2TIME(tMS);
295  std::vector<VehicleData> ret;
296  for (VehicleDataCont::const_iterator i = myVehicleDataCont.begin(); i != myVehicleDataCont.end(); ++i) {
297  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
298  ret.push_back(*i);
299  }
300  }
301  for (VehicleDataCont::const_iterator i = myLastVehicleDataCont.begin(); i != myLastVehicleDataCont.end(); ++i) {
302  if ((*i).entryTimeM >= t || (leaveTime && (*i).leaveTimeM >= t)) {
303  ret.push_back(*i);
304  }
305  }
306  for (VehicleMap::const_iterator i = myVehiclesOnDet.begin(); i != myVehiclesOnDet.end(); ++i) {
307  SUMOVehicle* v = (*i).first;
309  d.speedM = v->getSpeed();
310  ret.push_back(d);
311  }
312  return ret;
313 }
314 
315 
316 /****************************************************************************/
317 
const double myPosition
Detector&#39;s position on lane [m].
Definition: MSInductLoop.h:341
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:260
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:347
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:328
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:167
T MAX2(T a, T b)
Definition: StdDefs.h:73
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
double getCurrentLength() const
Returns the length of the vehicle on the detector.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
#define TS
Definition: SUMOTime.h:51
VehicleMap myVehiclesOnDet
Data for vehicles that have entered the detector (vehicle -> enter time)
Definition: MSInductLoop.h:368
double speedM
Speed of the vehicle in [m/s].
Definition: MSInductLoop.h:277
VehicleDataCont myLastVehicleDataCont
Data of vehicles that have completely passed the detector in the last time interval.
Definition: MSInductLoop.h:360
#define SIMTIME
Definition: SUMOTime.h:71
VehicleDataCont myVehicleDataCont
Data of vehicles that have completely passed the detector.
Definition: MSInductLoop.h:357
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:66
~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:64
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:253
T MIN2(T a, T b)
Definition: StdDefs.h:67
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:350
#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:552
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:254
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:70
bool closeTag()
Closes the most recently opened tag.
static bool gSemiImplicitEulerUpdate
Definition: MSGlobals.h:62
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:51
double getCurrentOccupancy() const
Returns the current occupancy.
double myLastLeaveTime
Leave-time of the last vehicle detected [s].
Definition: MSInductLoop.h:344
virtual double getSpeed() const =0
Returns the vehicle&#39;s current speed.
Representation of a lane in the micro simulation.
Definition: MSLane.h:77
static double lengthSum(double sumSoFar, const MSInductLoop::VehicleData &data)
Adds up VehicleData::lengthM.
Definition: MSInductLoop.h:333
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.