Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSMeanData.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2026 German Aerospace Center (DLR) and others.
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// https://www.eclipse.org/legal/epl-2.0/
7// This Source Code may also be made available under the following Secondary
8// Licenses when the conditions for such availability set forth in the Eclipse
9// Public License 2.0 are satisfied: GNU General Public License, version 2
10// or later which is available at
11// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13/****************************************************************************/
22// Data collector for edges/lanes
23/****************************************************************************/
24#include <config.h>
25
26#include <limits>
27#ifdef HAVE_FOX
29#endif
35#include <microsim/MSEdge.h>
36#include <microsim/MSLane.h>
37#include <microsim/MSVehicle.h>
39#include <microsim/MSNet.h>
40#include "MSMeanData_Amitran.h"
41#include "MSMeanData.h"
42
43#include <microsim/MSGlobals.h>
44#include <mesosim/MESegment.h>
45#include <mesosim/MELoop.h>
46
47
48// ===========================================================================
49// debug constants
50// ===========================================================================
51//#define DEBUG_NOTIFY_MOVE
52//#define DEBUG_NOTIFY_ENTER
53
54// ===========================================================================
55// method definitions
56// ===========================================================================
57// ---------------------------------------------------------------------------
58// MSMeanData::MeanDataValues - methods
59// ---------------------------------------------------------------------------
61 MSLane* const lane, const double length, const bool doAdd,
62 const MSMeanData* const parent) :
63 MSMoveReminder("meandata_" + (parent == nullptr ? "" : parent->getID() + "|") + (lane == nullptr ? "NULL" : lane->getID()), lane, doAdd),
64 myParent(parent),
65 myLaneLength(length),
66 sampleSeconds(0),
67 travelledDistance(0) { }
68
69
72
73
74bool
76#ifdef DEBUG_NOTIFY_ENTER
77 std::cout << "\n" << SIMTIME << " MSMeanData_Net::MSLaneMeanDataValues: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
78#else
79 UNUSED_PARAMETER(enteredLane);
80#endif
81 UNUSED_PARAMETER(reason);
82 return myParent == nullptr || myParent->vehicleApplies(veh);
83}
84
85
86bool
87MSMeanData::MeanDataValues::notifyMove(SUMOTrafficObject& veh, double oldPos, double newPos, double newSpeed) {
88 // if the vehicle has arrived, the reminder must be kept so it can be
89 // notified of the arrival subsequently
90 const double oldSpeed = veh.getPreviousSpeed();
91 double enterSpeed = MSGlobals::gSemiImplicitEulerUpdate ? newSpeed : oldSpeed; // NOTE: For the euler update, the vehicle is assumed to travel at constant speed for the whole time step
92 double leaveSpeed = newSpeed, leaveSpeedFront = newSpeed;
93
94 // These values will be further decreased below
95 double timeOnLane = TS;
96 double frontOnLane = oldPos > myLaneLength ? 0. : TS;
97 bool ret = true;
98
99 // entry and exit times (will be modified below)
100 double timeBeforeEnter = 0.;
101 double timeBeforeEnterBack = 0.;
102 double timeBeforeLeaveFront = newPos <= myLaneLength ? TS : 0.;
103 double timeBeforeLeave = TS;
104
105 // Treat the case that the vehicle entered the lane in the last step
106 if (oldPos < 0 && newPos >= 0) {
107 // Vehicle was not on this lane in the last time step
108 timeBeforeEnter = MSCFModel::passingTime(oldPos, 0, newPos, oldSpeed, newSpeed);
109 timeOnLane = TS - timeBeforeEnter;
110 frontOnLane = timeOnLane;
111 enterSpeed = MSCFModel::speedAfterTime(timeBeforeEnter, oldSpeed, newPos - oldPos);
112 }
113
114 const double oldBackPos = oldPos - veh.getVehicleType().getLength();
115 const double newBackPos = newPos - veh.getVehicleType().getLength();
116
117 // Determine the time before the vehicle back enters
118 if (oldBackPos < 0. && newBackPos > 0.) {
119 timeBeforeEnterBack = MSCFModel::passingTime(oldBackPos, 0., newBackPos, oldSpeed, newSpeed);
120 } else if (newBackPos <= 0) {
121 timeBeforeEnterBack = TS;
122 } else {
123 timeBeforeEnterBack = 0.;
124 }
125
126 // Treat the case that the vehicle's back left the lane in the last step
127 if (newBackPos > myLaneLength // vehicle's back has left the lane
128 && oldBackPos <= myLaneLength) { // and hasn't left the lane before
129 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0); // how could it move across the lane boundary otherwise
130 // (Leo) vehicle left this lane (it can also have skipped over it in one time step -> therefore we use "timeOnLane -= ..." and ( ... - timeOnLane) below)
131 timeBeforeLeave = MSCFModel::passingTime(oldBackPos, myLaneLength, newBackPos, oldSpeed, newSpeed);
132 const double timeAfterLeave = TS - timeBeforeLeave;
133 timeOnLane -= timeAfterLeave;
134 leaveSpeed = MSCFModel::speedAfterTime(timeBeforeLeave, oldSpeed, newPos - oldPos);
135 // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
136 if (fabs(timeOnLane) < NUMERICAL_EPS) { // reduce rounding errors
137 timeOnLane = 0.;
138 }
139 ret = veh.hasArrived();
140 }
141
142 // Treat the case that the vehicle's front left the lane in the last step
143 if (newPos > myLaneLength && oldPos <= myLaneLength) {
144 // vehicle's front has left the lane and has not left before
145 assert(!MSGlobals::gSemiImplicitEulerUpdate || newSpeed != 0);
146 timeBeforeLeaveFront = MSCFModel::passingTime(oldPos, myLaneLength, newPos, oldSpeed, newSpeed);
147 const double timeAfterLeave = TS - timeBeforeLeaveFront;
148 frontOnLane -= timeAfterLeave;
149 // XXX: Do we really need this? Why would this "reduce rounding errors"? (Leo) Refs. #2579
150 if (fabs(frontOnLane) < NUMERICAL_EPS) { // reduce rounding errors
151 frontOnLane = 0.;
152 }
153 leaveSpeedFront = MSCFModel::speedAfterTime(timeBeforeLeaveFront, oldSpeed, newPos - oldPos);
154 }
155
156 assert(frontOnLane <= TS);
157 assert(timeOnLane <= TS);
158
159 if (timeOnLane < 0) {
160 WRITE_ERRORF(TL("Negative vehicle step fraction for '%' on lane '%'."), veh.getID(), getLane()->getID());
161 return veh.hasArrived();
162 }
163 if (timeOnLane == 0) {
164 return veh.hasArrived();
165 }
166
167#ifdef DEBUG_NOTIFY_MOVE
168 std::stringstream ss;
169 ss << "\n"
170 << "lane length: " << myLaneLength
171 << "\noldPos: " << oldPos
172 << "\nnewPos: " << newPos
173 << "\noldPosBack: " << oldBackPos
174 << "\nnewPosBack: " << newBackPos
175 << "\ntimeBeforeEnter: " << timeBeforeEnter
176 << "\ntimeBeforeEnterBack: " << timeBeforeEnterBack
177 << "\ntimeBeforeLeaveFront: " << timeBeforeLeaveFront
178 << "\ntimeBeforeLeave: " << timeBeforeLeave;
179 if (!(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront))
180 || !(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront))) {
181 WRITE_ERROR(ss.str());
182 } else {
183 std::cout << ss.str() << std::endl;
184 }
185
186#endif
187
188 assert(timeBeforeEnter <= MIN2(timeBeforeEnterBack, timeBeforeLeaveFront));
189 assert(timeBeforeLeave >= MAX2(timeBeforeEnterBack, timeBeforeLeaveFront));
190 // compute average vehicle length on lane in last step
191 double vehLength = veh.getVehicleType().getLength();
192 // occupied lane length at timeBeforeEnter (resp. stepStart if already on lane)
193 double lengthOnLaneAtStepStart = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (oldPos - myLaneLength), oldPos));
194 // occupied lane length at timeBeforeLeave (resp. stepEnd if still on lane)
195 double lengthOnLaneAtStepEnd = MAX2(0., MIN4(myLaneLength, vehLength, vehLength - (newPos - myLaneLength), newPos));
196 double integratedLengthOnLane = 0.;
197 if (timeBeforeEnterBack < timeBeforeLeaveFront) {
198 // => timeBeforeLeaveFront>0, myLaneLength>vehLength
199 // vehicle length on detector at timeBeforeEnterBack
200 double lengthOnLaneAtBackEnter = MIN2(veh.getVehicleType().getLength(), newPos);
201 // linear quadrature of occupancy between timeBeforeEnter and timeBeforeEnterBack
202 integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeEnter) * (lengthOnLaneAtBackEnter + lengthOnLaneAtStepStart) * 0.5;
203 // linear quadrature of occupancy between timeBeforeEnterBack and timeBeforeLeaveFront
204 // (vehicle is completely on the edge in between)
205 integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnterBack) * vehLength;
206 // and until vehicle leaves/stepEnd
207 integratedLengthOnLane += (timeBeforeLeave - timeBeforeLeaveFront) * (vehLength + lengthOnLaneAtStepEnd) * 0.5;
208 } else if (timeBeforeEnterBack >= timeBeforeLeaveFront) {
209 // => myLaneLength <= vehLength or (timeBeforeLeaveFront == timeBeforeEnterBack == 0)
210 // vehicle length on detector at timeBeforeLeaveFront
211 double lengthOnLaneAtLeaveFront;
212 if (timeBeforeLeaveFront == timeBeforeEnter) {
213 // for the case that front already left
214 lengthOnLaneAtLeaveFront = lengthOnLaneAtStepStart;
215 } else if (timeBeforeLeaveFront == timeBeforeLeave) {
216 // for the case that front doesn't leave in this step
217 lengthOnLaneAtLeaveFront = lengthOnLaneAtStepEnd;
218 } else {
219 lengthOnLaneAtLeaveFront = myLaneLength;
220 }
221#ifdef DEBUG_NOTIFY_MOVE
222 std::cout << "lengthOnLaneAtLeaveFront=" << lengthOnLaneAtLeaveFront << std::endl;
223#endif
224 // linear quadrature of occupancy between timeBeforeEnter and timeBeforeLeaveFront
225 integratedLengthOnLane += (timeBeforeLeaveFront - timeBeforeEnter) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepStart) * 0.5;
226 // linear quadrature of occupancy between timeBeforeLeaveFront and timeBeforeEnterBack
227 integratedLengthOnLane += (timeBeforeEnterBack - timeBeforeLeaveFront) * lengthOnLaneAtLeaveFront;
228 // and until vehicle leaves/stepEnd
229 integratedLengthOnLane += (timeBeforeLeave - timeBeforeEnterBack) * (lengthOnLaneAtLeaveFront + lengthOnLaneAtStepEnd) * 0.5;
230 }
231
232 double meanLengthOnLane = integratedLengthOnLane / TS;
233#ifdef DEBUG_NOTIFY_MOVE
234 std::cout << "Calculated mean length on lane '" << myLane->getID() << "' in last step as " << meanLengthOnLane
235 << "\nlengthOnLaneAtStepStart=" << lengthOnLaneAtStepStart << ", lengthOnLaneAtStepEnd=" << lengthOnLaneAtStepEnd << ", integratedLengthOnLane=" << integratedLengthOnLane
236 << std::endl;
237#endif
238
239// // XXX: use this, when #2556 is fixed! Refs. #2575
240// const double travelledDistanceFrontOnLane = MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
241// const double travelledDistanceVehicleOnLane = MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
242// // XXX: #2556 fixed for ballistic update
243 const double travelledDistanceFrontOnLane = MSGlobals::gSemiImplicitEulerUpdate ? frontOnLane * newSpeed
244 : MAX2(0., MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.));
245 const double travelledDistanceVehicleOnLane = MSGlobals::gSemiImplicitEulerUpdate ? timeOnLane * newSpeed
246 : MIN2(newPos, myLaneLength) - MAX2(oldPos, 0.) + MIN2(MAX2(0., newPos - myLaneLength), veh.getVehicleType().getLength());
247// // XXX: no fix
248// const double travelledDistanceFrontOnLane = frontOnLane*newSpeed;
249// const double travelledDistanceVehicleOnLane = timeOnLane*newSpeed;
250
251#ifdef HAVE_FOX
252 ScopedLocker<> lock(myNotificationMutex, MSGlobals::gNumSimThreads > 1);
253#endif
254 notifyMoveInternal(veh, frontOnLane, timeOnLane, (enterSpeed + leaveSpeedFront) / 2., (enterSpeed + leaveSpeed) / 2., travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
255 return ret;
256}
257
258
259bool
260MSMeanData::MeanDataValues::notifyLeave(SUMOTrafficObject& /*veh*/, double /*lastPos*/, MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
262 return false; // reminder is re-added on every segment (@recheck for performance)
263 }
265}
266
267
268bool
270 return sampleSeconds == 0;
271}
272
273
274void
277
278
279double
281 return sampleSeconds;
282}
283
284
285// ---------------------------------------------------------------------------
286// MSMeanData::MeanDataValueTracker - methods
287// ---------------------------------------------------------------------------
289 const double length,
290 const MSMeanData* const parent)
291 : MSMeanData::MeanDataValues(lane, length, true, parent) {
292 myCurrentData.push_back(std::make_shared<TrackerEntry>(parent->createValuesSubData(lane, length, false)));
293}
294
295
297
298
299void
301 if (afterWrite) {
302 if (!myCurrentData.empty()) {
303 myCurrentData.pop_front();
304 }
305 } else {
306 myCurrentData.push_back(std::make_shared<TrackerEntry>(myParent->createValuesSubData(myLane, myLaneLength, false)));
307 }
308}
309
310
311void
313 myCurrentData.front()->myValues->addTo(val);
314}
315
316
317void
318MSMeanData::MeanDataValueTracker::notifyMoveInternal(const SUMOTrafficObject& veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane) {
319 myTrackedData[&veh]->myValues->notifyMoveInternal(veh, frontOnLane, timeOnLane, meanSpeedFrontOnLane, meanSpeedVehicleOnLane, travelledDistanceFrontOnLane, travelledDistanceVehicleOnLane, meanLengthOnLane);
320}
321
322
323bool
325 if (myParent == nullptr || reason != MSMoveReminder::NOTIFICATION_SEGMENT) {
326 myTrackedData[&veh]->myNumVehicleLeft++;
327 }
328 return myTrackedData[&veh]->myValues->notifyLeave(veh, lastPos, reason);
329}
330
331
332bool
334#ifdef DEBUG_NOTIFY_ENTER
335 std::cout << "\n" << SIMTIME << " MSMeanData::MeanDataValueTracker: veh '" << veh.getID() << "' enters lane '" << enteredLane->getID() << "'" << std::endl;
336#else
337 UNUSED_PARAMETER(enteredLane);
338#endif
340 return true;
341 }
342 if (myParent->vehicleApplies(veh) && myTrackedData.find(&veh) == myTrackedData.end()) {
343 myTrackedData[&veh] = myCurrentData.back();
344 myTrackedData[&veh]->myNumVehicleEntered++;
345 if (!myTrackedData[&veh]->myValues->notifyEnter(veh, reason)) {
346 myTrackedData[&veh]->myNumVehicleLeft++;
347 myTrackedData.erase(&veh);
348 return false;
349 }
350 return true;
351 }
352 return false;
353}
354
355
356bool
358 return myCurrentData.front()->myValues->isEmpty();
359}
360
361
362void
364 const SumoXMLAttrMask& attributeMask,
365 const SUMOTime period,
366 const int numLanes,
367 const double speedLimit,
368 const double defaultTravelTime,
369 const int /*numVehicles*/) const {
370 myCurrentData.front()->myValues->write(dev, attributeMask, period, numLanes, speedLimit,
371 defaultTravelTime,
372 myCurrentData.front()->myNumVehicleEntered);
373}
374
375
376int
378 int result = 0;
379 for (const auto& it : myCurrentData) {
380 if (it->myNumVehicleEntered == it->myNumVehicleLeft) {
381 result++;
382 } else {
383 break;
384 }
385 }
386 return result;
387}
388
389
390double
392 return myCurrentData.front()->myValues->getSamples();
393}
394
395
396// ---------------------------------------------------------------------------
397// MSMeanData - methods
398// ---------------------------------------------------------------------------
399MSMeanData::MSMeanData(const std::string& id,
400 const SUMOTime dumpBegin, const SUMOTime dumpEnd,
401 const bool useLanes, const std::string& excludeEmpty, const bool withInternal,
402 const bool trackVehicles,
403 const int detectPersons,
404 const double maxTravelTime,
405 const double minSamples,
406 const std::string& vTypes,
407 const std::string& writeAttributes,
408 const std::vector<MSEdge*>& edges,
409 AggregateType aggregate) :
410 MSDetectorFileOutput(id, vTypes, "", detectPersons),
411 myMinSamples(minSamples),
412 myMaxTravelTime(maxTravelTime),
413 myAmEdgeBased(!useLanes),
414 myDumpBegin(dumpBegin),
415 myDumpEnd(dumpEnd),
417 myLastResetTime(dumpBegin),
418 myEdges(edges),
419 myDumpInternal(withInternal && MSGlobals::gUsingInternalLanes),
420 myTrackVehicles(trackVehicles),
421 myWrittenAttributes(OutputDevice::parseWrittenAttributes(StringTokenizer(writeAttributes).getVector(), "meandata '" + id + "'")),
422 myAggregate(aggregate) {
423 try {
424 myDumpEmpty = !StringUtils::toBool(excludeEmpty);
425 } catch (const BoolFormatException&) {
426 if (excludeEmpty == "default" || excludeEmpty == "defaults") {
427 myPrintDefaults = true;
428 } else if (excludeEmpty == "modified") {
429 myDumpEmpty = false;
430 myPrintDefaults = true;
431 myPrintModified = true;
432 } else {
433 throw;
434 }
435 }
436}
437
438
439void
442 if (myEdges.empty()) {
443 // use all edges by default
444 for (MSEdge* const edge : MSNet::getInstance()->getEdgeControl().getEdges()) {
445 if ((myDumpInternal || !edge->isInternal()) &&
446 ((detectsPersons() && myDumpInternal) || (!edge->isCrossing() && !edge->isWalkingArea()))) {
447 myEdges.push_back(edge);
448 }
449 }
450 }
451 int index = 0;
452 for (MSEdge* edge : myEdges) {
453 myMeasures.push_back(std::vector<MeanDataValues*>());
454 myEdgeIndex[edge] = index++;
455 const std::vector<MSLane*>& lanes = edge->getLanes();
457 MeanDataValues* data;
458 if (!myAmEdgeBased) {
459 for (MSLane* const lane : lanes) {
460 data = createValues(lane, lanes[0]->getLength(), false);
461 myMeasures.back().push_back(data);
463 while (s != nullptr) {
464 s->addDetector(data, lane->getIndex());
465 s->prepareDetectorForWriting(*data, lane->getIndex());
466 s = s->getNextSegment();
467 }
468 data->reset();
469 data->reset(true);
470 }
471 } else {
472 if (myTrackVehicles) {
473 data = new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this);
474 } else {
475 data = createValues(nullptr, lanes[0]->getLength(), false);
476 }
477 data->setDescription("meandata_" + getID() + "|" + edge->getID());
478 myMeasures.back().push_back(data);
480 while (s != nullptr) {
481 s->addDetector(data);
483 s = s->getNextSegment();
484 }
485 data->reset();
486 data->reset(true);
487 }
488 continue;
489 }
491 myMeasures.back().push_back(new MeanDataValueTracker(nullptr, lanes[0]->getLength(), this));
492 }
493 for (MSLane* const lane : lanes) {
494 if (myTrackVehicles) {
495 if (myAmEdgeBased) {
496 lane->addMoveReminder(myMeasures.back().back());
497 } else {
498 myMeasures.back().push_back(new MeanDataValueTracker(lane, lane->getLength(), this));
499 }
500 } else {
501 myMeasures.back().push_back(createValues(lane, lane->getLength(), true));
502 }
503 }
504 }
506 for (const MSEdge* e : MSEdge::getAllEdges()) {
507 if (e->isTazConnector()) {
508 myTAZ.push_back(e);
509 }
510 }
511 }
512 if (mySubData != nullptr) {
513 mySubData->init();
514 std::vector<std::vector<MeanDataValues*> >::const_iterator subMeasureList = mySubData->myMeasures.begin();
515 for (const std::vector<MeanDataValues*>& valueList : myMeasures) {
516 std::vector<MeanDataValues*>::const_iterator subMeasures = subMeasureList->begin();
517 for (MeanDataValues* values : valueList) {
518 values->setSubData(*subMeasures);
519 subMeasures++;
520 }
521 subMeasureList++;
522 }
523 }
524}
525
526
528 for (const std::vector<MeanDataValues*>& valueList : myMeasures) {
529 for (MeanDataValues* const values : valueList) {
530 delete values;
531 }
532 }
533 delete mySubData;
534}
535
536
537void
539 UNUSED_PARAMETER(stopTime);
541 MSEdgeVector::iterator edge = myEdges.begin();
542 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i, ++edge) {
544 for (MeanDataValues* data : *i) {
545 while (s != nullptr) {
547 s = s->getNextSegment();
548 }
549 data->reset();
550 }
551 }
552 return;
553 }
554 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
555 for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
556 (*j)->reset();
557 }
558 }
559}
560
561
562std::string
563MSMeanData::getEdgeID(const MSEdge* const edge) {
564 return edge->getID();
565}
566
567
568void
570 if (myTrackVehicles) {
571 throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
572 }
573
574 double edgeLengthSum = 0;
575 int laneNumber = 0;
576 double speedSum = 0;
577 double totalTT = 0;
578 for (MSEdge* edge : myEdges) {
579 edgeLengthSum += edge->getLength();
580 laneNumber += edge->getNumDrivingLanes();
581 speedSum += edge->getSpeedLimit();
582 totalTT += edge->getLength() / edge->getSpeedLimit();
583 }
584 MeanDataValues* sumData = createValuesSubData(nullptr, edgeLengthSum, false);
585 for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
586 for (MeanDataValues* meanData : edgeValues) {
587 meanData->addTo(*sumData);
589 meanData->reset();
590 }
591 }
592 }
594 for (int i = 0; i < (int)myEdges.size(); i++) {
595 MSEdge* edge = myEdges[i];
596 std::vector<MeanDataValues*>& edgeValues = myMeasures[i];
598 while (s != nullptr) {
599 for (MeanDataValues* meanData : edgeValues) {
600 s->prepareDetectorForWriting(*meanData);
601 meanData->addTo(*sumData);
603 meanData->reset();
604 }
605 }
606 s = s->getNextSegment();
607 }
608 }
609 }
610
611 if (myDumpEmpty || !sumData->isEmpty()) {
612 writePrefix(dev, *sumData, SUMO_TAG_EDGE, "AGGREGATED");
614 for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
615 data->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)myEdges.size(),
616 myPrintDefaults ? totalTT : -1.);
617 }
618 dev.closeTag();
619 }
620 delete sumData;
621}
622
623
624void
626 if (myTrackVehicles) {
627 throw ProcessError(TL("aggregated meanData output not yet implemented for trackVehicles"));
628 }
629
630 for (const MSEdge* taz : myTAZ) {
631 double edgeLengthSum = 0;
632 int laneNumber = 0;
633 double speedSum = 0;
634 double totalTT = 0;
635 std::set<const MSEdge*> connected;
636 for (const MSEdge* edge : taz->getSuccessors()) {
637 connected.insert(edge);
638 }
639 for (const MSEdge* edge : taz->getPredecessors()) {
640 connected.insert(edge);
641 }
642 for (const MSEdge* edge : connected) {
643 edgeLengthSum += edge->getLength();
644 laneNumber += edge->getNumDrivingLanes();
645 speedSum += edge->getSpeedLimit();
646 totalTT += edge->getLength() / edge->getSpeedLimit();
647 }
648 MeanDataValues* sumData = createValuesSubData(nullptr, edgeLengthSum, false);
649 for (int i = 0; i < (int)myEdges.size(); i++) {
650 MSEdge* edge = myEdges[i];
651 if (connected.count(edge) != 0) {
652 std::vector<MeanDataValues*>& edgeValues = myMeasures[i];
655 while (s != nullptr) {
656 for (MeanDataValues* meanData : edgeValues) {
657 s->prepareDetectorForWriting(*meanData);
658 meanData->addTo(*sumData);
659 }
660 s = s->getNextSegment();
661 }
662 } else {
663 for (MeanDataValues* meanData : edgeValues) {
664 meanData->addTo(*sumData);
665 }
666 }
667 }
668 }
669 if (myDumpEmpty || !sumData->isEmpty()) {
670 writePrefix(dev, *sumData, SUMO_TAG_EDGE, taz->getID());
671 dev.writeAttr(SUMO_ATTR_NUMEDGES, connected.size());
672 for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
673 data->write(dev, myWrittenAttributes, stopTime - startTime, laneNumber, speedSum / (double)connected.size(),
674 myPrintDefaults ? totalTT : -1.);
675 }
676 dev.closeTag();
677 }
678 delete sumData;
679 }
680
682 for (const std::vector<MeanDataValues*>& edgeValues : myMeasures) {
683 for (MeanDataValues* meanData : edgeValues) {
684 meanData->reset();
685 }
686 }
687 }
688}
689
690
691void
693 const std::vector<MeanDataValues*>& edgeValues,
694 const MSEdge* const edge, SUMOTime startTime, SUMOTime stopTime) {
696 int idx = 0;
697 for (MeanDataValues* const data : edgeValues) {
699 while (s != nullptr) {
700 s->prepareDetectorForWriting(*data, myAmEdgeBased ? -1 : idx);
701 s = s->getNextSegment();
702 }
703 idx++;
704 }
705 if (myAmEdgeBased) {
706 MeanDataValues* const data = edgeValues.front();
707 if (myDumpEmpty || (myPrintModified && edge->getLanes()[0]->isSpeedModified()) || !data->isEmpty()) {
708 writePrefix(dev, *data, SUMO_TAG_EDGE, getEdgeID(edge));
709 for (MeanDataValues* d = data; d != nullptr; d = d->getSubData()) {
710 d->write(dev, myWrittenAttributes, stopTime - startTime,
711 edge->getNumDrivingLanes(),
712 edge->getSpeedLimit(),
713 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
714 }
715 dev.closeTag();
716 }
718 data->reset(true);
719 }
720 return;
721 }
722 }
723 if (!myAmEdgeBased) {
724 bool writeCheck = myDumpEmpty;
725 if (!writeCheck) {
726 for (const MeanDataValues* const laneData : edgeValues) {
727 if (!laneData->isEmpty() || (myPrintModified && laneData->getLane()->isSpeedModified())) {
728 writeCheck = true;
729 break;
730 }
731 }
732 }
733 if (writeCheck) {
735 }
736 for (MeanDataValues* const laneData : edgeValues) {
737 const MSLane* const lane = laneData->getLane();
738 if (myDumpEmpty || (myPrintModified && lane->isSpeedModified()) || !laneData->isEmpty()) {
739 writePrefix(dev, *laneData, SUMO_TAG_LANE, lane->getID());
740 for (MeanDataValues* data = laneData; data != nullptr; data = data->getSubData()) {
741 data->write(dev, myWrittenAttributes, stopTime - startTime, 1, lane->getSpeedLimit(),
742 myPrintDefaults ? lane->getLength() / lane->getSpeedLimit() : -1.);
743 }
744 dev.closeTag();
745 }
747 laneData->reset(true);
748 }
749 }
750 if (writeCheck) {
751 dev.closeTag();
752 }
753 } else {
754 if (myTrackVehicles) {
755 MeanDataValues* meanData = *edgeValues.begin();
756 if (myDumpEmpty || !meanData->isEmpty()) {
757 writePrefix(dev, *meanData, SUMO_TAG_EDGE, edge->getID());
758 for (MeanDataValues* data = meanData; data != nullptr; data = data->getSubData()) {
759 data->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
760 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
761 }
762 dev.closeTag();
763 }
765 meanData->reset(true);
766 }
767 } else {
768 MeanDataValues* sumData = createValuesSubData(nullptr, edge->getLength(), false);
769 bool writeCheck = myDumpEmpty;
770 for (MeanDataValues* const laneData : edgeValues) {
771 laneData->addTo(*sumData);
772 if (myPrintModified && laneData->getLane()->isSpeedModified()) {
773 writeCheck = true;
774 }
776 laneData->reset();
777 }
778 }
779 if (writeCheck || !sumData->isEmpty()) {
780 writePrefix(dev, *sumData, SUMO_TAG_EDGE, getEdgeID(edge));
781 for (MeanDataValues* data = sumData; data != nullptr; data = data->getSubData()) {
782 data->write(dev, myWrittenAttributes, stopTime - startTime, edge->getNumDrivingLanes(), edge->getSpeedLimit(),
783 myPrintDefaults ? edge->getLength() / edge->getSpeedLimit() : -1.);
784 }
785 dev.closeTag();
786 }
787 delete sumData;
788 }
789 }
790}
791
792
793void
798
799
800void
801MSMeanData::writePrefix(OutputDevice& dev, const MeanDataValues& values, const SumoXMLTag tag, const std::string id) const {
802 dev.openTag(tag);
803 dev.writeAttr(SUMO_ATTR_ID, id);
805}
806
807
808void
810 SUMOTime startTime, SUMOTime stopTime) {
811 // check whether this dump shall be written for the current time
813 int numReady = myDumpBegin < stopTime && myDumpEnd - DELTA_T >= startTime ? 1 : 0;
814 if (myTrackVehicles && myDumpBegin < stopTime) {
815 myPendingIntervals.push_back(std::make_pair(startTime, stopTime));
816 numReady = (int)myPendingIntervals.size();
817 for (std::vector<std::vector<MeanDataValues*> >::const_iterator i = myMeasures.begin(); i != myMeasures.end(); ++i) {
818 for (std::vector<MeanDataValues*>::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
819 numReady = MIN2(numReady, ((MeanDataValueTracker*)*j)->getNumReady());
820 if (numReady == 0) {
821 break;
822 }
823 }
824 if (numReady == 0) {
825 break;
826 }
827 }
828 }
829 const bool partialInterval = startTime < myInitTime;
830 if (numReady == 0 || myTrackVehicles || partialInterval) {
831 resetOnly(stopTime);
832 }
833 if (partialInterval) {
834 return;
835 }
836 while (numReady-- > 0) {
837 if (!myPendingIntervals.empty()) {
838 startTime = myPendingIntervals.front().first;
839 stopTime = myPendingIntervals.front().second;
840 myPendingIntervals.pop_front();
841 }
842 openInterval(dev, startTime, stopTime);
844 writeAggregated(dev, startTime, stopTime);
845 } else if (myAggregate == AggregateType::TAZ) {
846 writeAggregatedTAZ(dev, startTime, stopTime);
847 } else {
848 MSEdgeVector::const_iterator edge = myEdges.begin();
849 for (const std::vector<MeanDataValues*>& measures : myMeasures) {
850 writeEdge(dev, measures, *edge, startTime, stopTime);
851 ++edge;
852 }
853 }
854 dev.closeTag();
855 }
856 dev.flush();
857}
858
859
860void
862 dev.writeXMLHeader("meandata", "meandata_file.xsd");
863}
864
865
866void
868 if (step + DELTA_T == myDumpBegin) {
869 init();
870 }
871}
872
873
874const std::vector<MSMeanData::MeanDataValues*>*
876 auto it = myEdgeIndex.find(edge);
877 if (it != myEdgeIndex.end()) {
878 return &myMeasures[it->second];
879 } else {
880 return nullptr;
881 }
882}
883
884
885const std::vector<MSMoveReminder*>
887 std::vector<MSMoveReminder*> result;
888 for (auto vec : myMeasures) {
889 result.insert(result.end(), vec.begin(), vec.end());
890 }
891 return result;
892}
893
894
895double
896MSMeanData::getAttributeValue(const MSLane* lane, SumoXMLAttr a, double defaultValue) const {
897 double result = defaultValue;
898 const std::vector<MeanDataValues*>* edgeValues = getEdgeValues(&lane->getEdge());
899 if (edgeValues == nullptr) {
900 return result;
901 }
902 MeanDataValues* values = nullptr;
903 if (!myAmEdgeBased) {
904 values = (*edgeValues)[lane->getIndex()];
905 } else {
906 MeanDataValues* sumData = createValuesSubData(nullptr, lane->getLength(), false);
907 for (MeanDataValues* meanData : (*edgeValues)) {
908 meanData->addTo(*sumData);
909 }
910 values = sumData;
911 }
912 const SUMOTime period = SIMSTEP - myLastResetTime;
913 result = values->getAttributeValue(a, period, lane->getEdge().getNumLanes(), lane->getSpeedLimit());
914 if (myAmEdgeBased) {
915 delete values;
916 }
917 return result;
918}
919
920
922MSMeanData::createValuesSubData(MSLane* const lane, const double length, const bool doAdd) const {
923 MeanDataValues* values = createValues(lane, length, doAdd);
924 if (mySubData != nullptr) {
925 values->setSubData(mySubData->createValues(lane, length, doAdd));
926 }
927 return values;
928}
929
930
931/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
SUMOTime DELTA_T
Definition SUMOTime.cpp:38
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:91
#define SIMSTEP
Definition SUMOTime.h:69
#define SUMOTime_MAX
Definition SUMOTime.h:34
#define TS
Definition SUMOTime.h:45
#define SIMTIME
Definition SUMOTime.h:70
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_INTERVAL
an aggreagated-output interval
@ SUMO_TAG_LANE
begin/end of the description of a single lane
@ SUMO_TAG_EDGE
begin/end of the description of an edge
std::bitset< 96 > SumoXMLAttrMask
AggregateType
Numbers representing special SUMO-XML-attribute values Information on edgeData/laneData output should...
SumoXMLAttr
Numbers representing SUMO-XML - attributes.
@ SUMO_ATTR_NUMEDGES
@ SUMO_ATTR_BEGIN
weights: time range begin
@ SUMO_ATTR_END
weights: time range end
@ SUMO_ATTR_SAMPLEDSECONDS
MSMeanData_Net.
@ SUMO_ATTR_ID
T MIN4(T a, T b, T c, T d)
Definition StdDefs.h:107
T MIN2(T a, T b)
Definition StdDefs.h:80
T MAX2(T a, T b)
Definition StdDefs.h:86
MESegment * getSegmentForEdge(const MSEdge &e, double pos=0)
Get the segment for a given edge at a given position.
Definition MELoop.cpp:384
A single mesoscopic segment (cell)
Definition MESegment.h:50
void addDetector(MSMoveReminder *data, int queueIndex=-1)
Adds a data collector for a detector to this segment.
void prepareDetectorForWriting(MSMoveReminder &data, int queueIndex=-1)
Removes a data collector for a detector from this segment.
MESegment * getNextSegment() const
Returns the following segment on the same edge (0 if it is the last).
Definition MESegment.h:246
static double speedAfterTime(const double t, const double oldSpeed, const double dist)
Calculates the speed after a time t \in [0,TS] given the initial speed and the distance traveled in a...
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...
Base of value-generating classes (detectors)
const MSEdgeVector & getEdges() const
Returns loaded edges.
A road/street connecting two junctions.
Definition MSEdge.h:77
static const MSEdgeVector & getAllEdges()
Returns all edges with a numerical id.
Definition MSEdge.cpp:1144
const std::vector< MSLane * > & getLanes() const
Returns this edge's lanes.
Definition MSEdge.h:168
int getNumDrivingLanes() const
return the number of lanes that permit non-weak modes if the edge allows non weak modes and the numbe...
Definition MSEdge.cpp:1578
double getSpeedLimit() const
Returns the speed limit of the edge @caution The speed limit of the first lane is returned; should pr...
Definition MSEdge.cpp:1216
double getLength() const
return the length of the edge
Definition MSEdge.h:694
int getNumLanes() const
Definition MSEdge.h:172
static bool gUseMesoSim
Definition MSGlobals.h:106
static MELoop * gMesoNet
mesoscopic simulation infrastructure
Definition MSGlobals.h:115
static bool gSemiImplicitEulerUpdate
Definition MSGlobals.h:53
static int gNumSimThreads
how many threads to use for simulation
Definition MSGlobals.h:149
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getSpeedLimit() const
Returns the lane's maximum allowed speed.
Definition MSLane.h:602
double getLength() const
Returns the lane's length.
Definition MSLane.h:632
int getIndex() const
Returns the lane's index.
Definition MSLane.h:668
bool isSpeedModified() const
Definition MSLane.h:594
MSEdge & getEdge() const
Returns the lane's edge.
Definition MSLane.h:790
Data structure for mean (aggregated) edge/lane values for tracked vehicles.
Definition MSMeanData.h:213
double getSamples() const
Returns the number of collected sample seconds.
MeanDataValueTracker(MSLane *const lane, const double length, const MSMeanData *const parent)
Constructor.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
void addTo(MSMeanData::MeanDataValues &val) const
Add the values of this to the given one and store them there.
void notifyMoveInternal(const SUMOTrafficObject &veh, const double frontOnLane, const double timeOnLane, const double meanSpeedFrontOnLane, const double meanSpeedVehicleOnLane, const double travelledDistanceFrontOnLane, const double travelledDistanceVehicleOnLane, const double meanLengthOnLane)
Internal notification about the vehicle moves.
void write(OutputDevice &dev, const SumoXMLAttrMask &attributeMask, const SUMOTime period, const int numLanes, const double speedLimit, const double defaultTravelTime, const int numVehicles=-1) const
Writes output values into the given stream.
std::list< std::shared_ptr< TrackerEntry > > myCurrentData
The currently active meandata "intervals".
Definition MSMeanData.h:312
virtual ~MeanDataValueTracker()
Destructor.
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Computes current values and adds them to their sums.
bool isEmpty() const
Returns whether any data was collected.
void reset(bool afterWrite)
Resets values so they may be used for the next interval.
Data structure for mean (aggregated) edge/lane values.
Definition MSMeanData.h:66
virtual void addTo(MeanDataValues &val) const =0
Add the values of this to the given one and store them there.
virtual bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle leaves the reminder's lane.
MeanDataValues(MSLane *const lane, const double length, const bool doAdd, const MSMeanData *const parent)
Constructor.
void setSubData(MeanDataValues *subData)
Definition MSMeanData.h:181
virtual void update()
Called if a per timestep update is needed. Default does nothing.
virtual bool isEmpty() const
Returns whether any data was collected.
MeanDataValues * getSubData()
Definition MSMeanData.h:177
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks whether the reminder still has to be notified about the vehicle moves.
virtual ~MeanDataValues()
Destructor.
virtual double getAttributeValue(SumoXMLAttr a, const SUMOTime period, const double numLanes, const double speedLimit) const
return attribute value
Definition MSMeanData.h:169
virtual void reset(bool afterWrite=false)=0
Resets values so they may be used for the next interval.
virtual bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Called if the vehicle enters the reminder's lane.
virtual double getSamples() const
Returns the number of collected sample seconds.
Data collector for edges/lanes.
Definition MSMeanData.h:57
virtual MSMeanData::MeanDataValues * createValues(MSLane *const lane, const double length, const bool doAdd) const =0
Create an instance of MeanDataValues.
void writeXMLOutput(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes collected values into the given stream.
virtual void writePrefix(OutputDevice &dev, const MeanDataValues &values, const SumoXMLTag tag, const std::string id) const
Writes the surrounding element into the given stream.
const bool myDumpInternal
Whether internal lanes/edges shall be written.
Definition MSMeanData.h:551
bool myPrintDefaults
Whether empty lanes/edges shall be written with default values.
Definition MSMeanData.h:545
const AggregateType myAggregate
whether the data for all edges shall be aggregated
Definition MSMeanData.h:560
const SUMOTime myDumpBegin
The first and the last time step to write information (-1 indicates always)
Definition MSMeanData.h:528
virtual void detectorUpdate(const SUMOTime step)
Updates the detector.
virtual ~MSMeanData()
Destructor.
SUMOTime myLastResetTime
time at which reset() was called
Definition MSMeanData.h:534
MSMeanData(const std::string &id, const SUMOTime dumpBegin, const SUMOTime dumpEnd, const bool useLanes, const std::string &excludeEmpty, const bool withInternal, const bool trackVehicles, const int detectPersons, const double minSamples, const double maxTravelTime, const std::string &vTypes, const std::string &writeAttributes, const std::vector< MSEdge * > &edges, AggregateType aggregate)
Constructor.
void writeAggregated(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes aggregated data of all edge values into the given stream.
void init()
Adds the value collectors to all relevant edges.
const double myMinSamples
the minimum sample seconds
Definition MSMeanData.h:512
void resetOnly(SUMOTime stopTime)
Resets network value in order to allow processing of the next interval.
void writeAggregatedTAZ(OutputDevice &dev, SUMOTime startTime, SUMOTime stopTime)
Writes aggregated data for each TAZ into the given stream.
std::map< const MSEdge *, int > myEdgeIndex
The index in myEdges / myMeasures.
Definition MSMeanData.h:542
const SumoXMLAttrMask myWrittenAttributes
bit mask for checking attributes to be written
Definition MSMeanData.h:557
MSMeanData * mySubData
more data collectors which write to the same output
Definition MSMeanData.h:563
const bool myAmEdgeBased
Information whether the output shall be edge-based (not lane-based)
Definition MSMeanData.h:524
SUMOTime myInitTime
time at which init was called();
Definition MSMeanData.h:531
const double myMaxTravelTime
the maximum travel time to write
Definition MSMeanData.h:515
bool myDumpEmpty
Whether empty lanes/edges shall be written.
Definition MSMeanData.h:521
const SUMOTime myDumpEnd
Definition MSMeanData.h:528
std::list< std::pair< SUMOTime, SUMOTime > > myPendingIntervals
The intervals for which output still has to be generated (only in the tracking case)
Definition MSMeanData.h:566
const std::vector< MeanDataValues * > * getEdgeValues(const MSEdge *edge) const
void writeEdge(OutputDevice &dev, const std::vector< MeanDataValues * > &edgeValues, const MSEdge *const edge, SUMOTime startTime, SUMOTime stopTime)
Writes edge values into the given stream.
virtual std::string getEdgeID(const MSEdge *const edge)
Return the relevant edge id.
virtual void writeXMLDetectorProlog(OutputDevice &dev) const
Opens the XML-output using "netstats" as root element.
MSMeanData::MeanDataValues * createValuesSubData(MSLane *const lane, const double length, const bool doAdd) const
Create an instance of MeanDataValues with subdata.
MSEdgeVector myEdges
The corresponding first edges.
Definition MSMeanData.h:537
const std::vector< MSMoveReminder * > getReminders() const
retrieve all MeanDataValues
virtual void openInterval(OutputDevice &dev, const SUMOTime startTime, const SUMOTime stopTime)
Writes the interval opener.
bool myPrintModified
Whether only empty lanes/edges which have been modified shall be written.
Definition MSMeanData.h:548
double getAttributeValue(const MSLane *lane, SumoXMLAttr a, double defaultValue) const
return attribute value for the given lane
std::vector< std::vector< MeanDataValues * > > myMeasures
Value collectors; sorted by edge, then by lane.
Definition MSMeanData.h:518
const bool myTrackVehicles
Whether vehicles are tracked.
Definition MSMeanData.h:554
ConstMSEdgeVector myTAZ
Definition MSMeanData.h:539
Something on a lane to be noticed about vehicle movement.
void setDescription(const std::string &description)
Notification
Definition of a vehicle state.
@ NOTIFICATION_SEGMENT
The vehicle changes the segment (meso only)
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:201
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
virtual bool skipFinalReset() const
gui may prevent final meanData reset to keep live data visible
Definition MSNet.h:852
MSEdgeControl & getEdgeControl()
Returns the edge control.
Definition MSNet.h:445
double getLength() const
Get vehicle's length [m].
std::string myID
The name of the object.
Definition Named.h:124
void addTo(const StoringVisitor &cont) const
Adds this object to the given container.
Definition Named.h:117
const std::string & getID() const
Returns the id.
Definition Named.h:73
Static storage of an output device and its base (abstract) implementation.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute
OutputDevice & writeOptionalAttr(const SumoXMLAttr attr, const T &val, const bool isNull=false, const bool escape=false)
writes a named attribute unless null
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
Representation of a vehicle, person, or container.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getPreviousSpeed() const =0
Returns the object's previous speed.
virtual bool hasArrived() const =0
Returns whether this object has arrived.
A scoped lock which only triggers on condition.
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
#define UNUSED_PARAMETER(x)