Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MSDevice_Tripinfo.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2009-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/****************************************************************************/
21// A device which collects info on the vehicle trip
22/****************************************************************************/
23#include <config.h>
24
25#include <microsim/MSGlobals.h>
26#include <microsim/MSNet.h>
27#include <microsim/MSLane.h>
28#include <microsim/MSEdge.h>
29#include <microsim/MSVehicle.h>
31#include <mesosim/MEVehicle.h>
35#include "MSDevice_Vehroutes.h"
36#include "MSDevice_Tripinfo.h"
37
38#define NOT_ARRIVED TIME2STEPS(-1)
39#define STATE_EMPTY_ARRIVALLANE "NONE"
40
41
42// ===========================================================================
43// static members
44// ===========================================================================
45std::set<const MSDevice_Tripinfo*, ComparatorNumericalIdLess> MSDevice_Tripinfo::myPendingOutput;
46
56
64
69std::vector<int> MSDevice_Tripinfo::myRideCount({0, 0});
70std::vector<int> MSDevice_Tripinfo::myRideBusCount({0, 0});
71std::vector<int> MSDevice_Tripinfo::myRideRailCount({0, 0});
72std::vector<int> MSDevice_Tripinfo::myRideTaxiCount({0, 0});
73std::vector<int> MSDevice_Tripinfo::myRideBikeCount({0, 0});
74std::vector<int> MSDevice_Tripinfo::myRideAbortCount({0, 0});
75std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideWaitingTime({0, 0});
76std::vector<double> MSDevice_Tripinfo::myTotalRideRouteLength({0., 0.});
77std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideDuration({0, 0});
78
79// ===========================================================================
80// method definitions
81// ===========================================================================
82// ---------------------------------------------------------------------------
83// static initialisation methods
84// ---------------------------------------------------------------------------
85void
87 oc.addOptionSubTopic("Tripinfo Device");
88 insertDefaultAssignmentOptions("tripinfo", "Tripinfo Device", oc);
89}
90
91
92void
93MSDevice_Tripinfo::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
95 const bool enableByOutputOption = oc.isSet("tripinfo-output") || oc.getBool("duration-log.statistics");
96 if (equippedByDefaultAssignmentOptions(oc, "tripinfo", v, enableByOutputOption)) {
97 MSDevice_Tripinfo* device = new MSDevice_Tripinfo(v, "tripinfo_" + v.getID());
98 into.push_back(device);
99 myPendingOutput.insert(device);
100 }
101}
102
103
104// ---------------------------------------------------------------------------
105// MSDevice_Tripinfo-methods
106// ---------------------------------------------------------------------------
107MSDevice_Tripinfo::MSDevice_Tripinfo(SUMOVehicle& holder, const std::string& id) :
108 MSVehicleDevice(holder, id),
109 myDepartLane(""),
110 myDepartSpeed(-1),
111 myDepartPosLat(0),
112 myWaitingTime(0),
113 myAmWaiting(false),
114 myWaitingCount(0),
115 myStoppingTime(0),
116 myParkingStarted(-1),
117 myArrivalTime(NOT_ARRIVED),
118 myArrivalLane(""),
119 myArrivalPos(-1),
120 myArrivalPosLat(0.),
121 myArrivalSpeed(-1),
122 myArrivalReason(MSMoveReminder::NOTIFICATION_ARRIVED),
123 myMesoTimeLoss(0),
124 myRouteLength(0.) {
125}
126
127
129 // ensure clean up for vaporized vehicles which do not generate output
130 myPendingOutput.erase(this);
131}
132
133void
135 myVehicleCount = 0;
137 myTotalSpeed = 0;
138 myTotalDuration = 0;
140 myTotalTimeLoss = 0;
143
144 myBikeCount = 0;
151
152 myWalkCount = 0;
156
157 myRideCount = {0, 0};
158 myRideBusCount = {0, 0};
159 myRideRailCount = {0, 0};
160 myRideTaxiCount = {0, 0};
161 myRideBikeCount = {0, 0};
162 myRideAbortCount = {0, 0};
163 myTotalRideWaitingTime = {0, 0};
164 myTotalRideRouteLength = {0., 0.};
165 myTotalRideDuration = {0, 0};
166}
167
168bool
170 if (veh.isVehicle()) {
172 if (!myAmWaiting) {
174 myAmWaiting = true;
175 }
176 }
177 return true;
178}
179
180
181bool
183 double /*newPos*/, double newSpeed) {
184 if (veh.isStopped()) {
185 if (newSpeed <= SUMO_const_haltingSpeed) {
187 }
188 } else if (newSpeed <= SUMO_const_haltingSpeed && lowAcceleration(veh)) {
190 if (!myAmWaiting) {
192 myAmWaiting = true;
193 }
194 } else {
195 myAmWaiting = false;
196 }
197 return true;
198}
199
200
201bool
204 // acceleration is not modelled
205 return false;
206 } else {
207 const MSVehicle& v = dynamic_cast<const MSVehicle&>(veh);
209 }
210}
211
212
213void
215 const double /* frontOnLane */,
216 const double timeOnLane,
217 const double /* meanSpeedFrontOnLane */,
218 const double meanSpeedVehicleOnLane,
219 const double /* travelledDistanceFrontOnLane */,
220 const double /* travelledDistanceVehicleOnLane */,
221 const double /* meanLengthOnLane */) {
222
223 // called by meso
224 const double vmax = veh.getEdge()->getVehicleMaxSpeed(&veh);
225 if (vmax > 0) {
226 myMesoTimeLoss += TIME2STEPS(timeOnLane * (vmax - meanSpeedVehicleOnLane) / vmax);
227 }
229}
230
231
232void
239
240bool
244 myDepartLane = static_cast<MSVehicle&>(veh).getLane()->getID();
245 myDepartPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
246 } else {
247 myDepartLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
248 }
249 myDepartSpeed = veh.getSpeed();
251 } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
252 // notifyMove is not called while parking
253 // @note insertion delay when resuming after parking is included
255 }
256 return true;
257}
258
259
260bool
262 MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
265 myArrivalReason = reason;
267 myArrivalLane = static_cast<MSVehicle&>(veh).getLane()->getID();
268 myArrivalPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
269 } else {
270 myArrivalLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
271 }
272 // @note vehicle may have moved past its arrivalPos during the last step
273 // due to non-zero arrivalspeed but we consider it as arrived at the desired position
274 // However, vaporization may happen anywhere (via TraCI)
276 // vaporized
278 } else {
280 }
281 myArrivalSpeed = veh.getSpeed();
283 } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
285 } else if (reason == NOTIFICATION_JUNCTION
286 || reason == NOTIFICATION_TELEPORT
290 } else {
291 const MSLane* lane = static_cast<MSVehicle&>(veh).getLane();
292 if (lane != nullptr) {
293 myRouteLength += lane->getLength();
294 }
295 }
296 }
297 return true;
298}
299
300
301void
303 const SUMOTime timeLoss = MSGlobals::gUseMesoSim ? myMesoTimeLoss : static_cast<MSVehicle&>(myHolder).getTimeLoss();
304 const double routeLength = myRouteLength + (myArrivalTime == NOT_ARRIVED ? myHolder.getPositionOnLane() : myArrivalPos);
305 SUMOTime duration = 0;
306 if (myHolder.hasDeparted()) {
308 if (myHolder.getVClass() == SVC_BICYCLE) {
309 myBikeCount++;
310 myTotalBikeRouteLength += routeLength;
311 myTotalBikeSpeed += routeLength / STEPS2TIME(duration);
312 myTotalBikeDuration += duration;
314 myTotalBikeTimeLoss += timeLoss;
316 } else {
318 myTotalRouteLength += routeLength;
319 myTotalSpeed += routeLength / STEPS2TIME(duration);
320 myTotalDuration += duration;
322 myTotalTimeLoss += timeLoss;
324 }
325 }
326
327 myPendingOutput.erase(this);
328 if (tripinfoOut == nullptr) {
329 return;
330 }
331 // write
332 OutputDevice& os = *tripinfoOut;
333 os.openTag("tripinfo").writeAttr("id", myHolder.getID());
335 os.writeAttr("departLane", myDepartLane);
336 os.writeAttr("departPos", myHolder.getDepartPos());
338 os.writeAttr("departPosLat", myDepartPosLat);
339 }
340 os.writeAttr("departSpeed", myDepartSpeed);
341 SUMOTime departDelay = myHolder.getDepartDelay();
343 if (!myHolder.hasDeparted()) {
344 assert(param.depart <= SIMSTEP || param.departProcedure != DepartDefinition::GIVEN);
345 departDelay = SIMSTEP - param.depart;
346 }
347 os.writeAttr("departDelay", time2string(departDelay));
348 os.writeAttr("arrival", time2string(myArrivalTime));
349 os.writeAttr("arrivalLane", myArrivalLane);
350 os.writeAttr("arrivalPos", myArrivalPos);
352 os.writeAttr("arrivalPosLat", myArrivalPosLat);
353 }
354 os.writeAttr("arrivalSpeed", myArrivalSpeed);
355 os.writeAttr("duration", time2string(duration));
356 os.writeAttr("routeLength", routeLength);
361 os.writeAttr("rerouteNo", myHolder.getNumberReroutes());
362 os.writeAttr("devices", toString(myHolder.getDevices()));
363 os.writeAttr("vType", myHolder.getVehicleType().getID());
364 os.writeAttr("speedFactor", myHolder.getChosenSpeedFactor());
365 std::string vaporized;
366 switch (myArrivalReason) {
368 vaporized = "calibrator";
369 break;
371 vaporized = "gui";
372 break;
374 vaporized = "collision";
375 break;
377 vaporized = "vaporizer";
378 break;
380 vaporized = "traci";
381 break;
383 vaporized = "teleport";
384 break;
385 default:
387 (param.arrivalEdge >= 0 && myHolder.getRoutePosition() >= param.arrivalEdge)) {
388 vaporized = "";
389 } else {
390 vaporized = "end";
391 }
392 break;
393 }
394 os.writeAttr("vaporized", vaporized);
395 // cannot close tag because emission device output might follow
396}
397
398
399void
401 MSNet* net = MSNet::getInstance();
402 OutputDevice* tripinfoOut = (OptionsCont::getOptions().isSet("tripinfo-output") ?
403 &OutputDevice::getDeviceByOption("tripinfo-output") : nullptr);
406 const bool writeUndeparted = OptionsCont::getOptions().getBool("tripinfo-output.write-undeparted");
407 const SUMOTime t = net->getCurrentTimeStep();
408 while (myPendingOutput.size() > 0) {
409 const MSDevice_Tripinfo* d = *myPendingOutput.begin();
410 const bool departed = d->myHolder.hasDeparted();
411 const bool departDelayed = d->myHolder.getParameter().depart <= t;
412 if (!departed && departDelayed) {
415 }
416 if (departed || (writeUndeparted && departDelayed)) {
417 const_cast<MSDevice_Tripinfo*>(d)->updateParkingStopTime();
418 d->generateOutput(tripinfoOut);
419 if (tripinfoOut != nullptr) {
420 for (MSVehicleDevice* const dev : d->myHolder.getDevices()) {
421 if (typeid(*dev) == typeid(MSDevice_Tripinfo) || typeid(*dev) == typeid(MSDevice_Vehroutes)) {
422 // tripinfo is special and vehroute has its own write-unfinished option
423 continue;
424 }
425 dev->generateOutput(tripinfoOut);
426 }
427 OutputDevice::getDeviceByOption("tripinfo-output").closeTag();
428 }
429 } else {
430 myPendingOutput.erase(d);
431 }
432 }
433 // unfinished persons
434 if (net->hasPersons()) {
435 net->getPersonControl().eraseAll();
436 }
437
438}
439
440
441void
442MSDevice_Tripinfo::addPedestrianData(double walkLength, SUMOTime walkDuration, SUMOTime walkTimeLoss) {
443 myWalkCount++;
444 myTotalWalkRouteLength += walkLength;
445 myTotalWalkDuration += walkDuration;
446 myTotalWalkTimeLoss += walkTimeLoss;
447}
448
449
450void
451MSDevice_Tripinfo::addRideTransportData(const bool isPerson, const double distance, const SUMOTime duration,
452 const SUMOVehicleClass vClass, const std::string& line, const SUMOTime waitingTime) {
453 const int index = isPerson ? 0 : 1;
454 myRideCount[index]++;
455 if (duration > 0) {
456 myTotalRideWaitingTime[index] += waitingTime;
457 myTotalRideRouteLength[index] += distance;
458 myTotalRideDuration[index] += duration;
459 if (vClass == SVC_BICYCLE) {
460 myRideBikeCount[index]++;
461 } else if (!line.empty()) {
462 if (isRailway(vClass)) {
463 myRideRailCount[index]++;
464 } else if (vClass == SVC_TAXI) {
465 myRideTaxiCount[index]++;
466 } else {
467 // some kind of road vehicle
468 myRideBusCount[index]++;
469 }
470 }
471 } else {
472 myRideAbortCount[index]++;
473 }
474}
475
476
477std::string
479 std::ostringstream msg;
480 msg.setf(msg.fixed);
481 msg.precision(gPrecision);
482 if (myBikeCount == 0 || myVehicleCount > 0) {
483 msg << "Statistics (avg of " << myVehicleCount << "):\n";
484 msg << " RouteLength: " << getAvgRouteLength() << "\n"
485 << " Speed: " << getAvgTripSpeed() << "\n"
486 << " Duration: " << getAvgDuration() << "\n"
487 << " WaitingTime: " << getAvgWaitingTime() << "\n"
488 << " TimeLoss: " << getAvgTimeLoss() << "\n"
489 << " DepartDelay: " << getAvgDepartDelay() << "\n";
490 }
491 if (myBikeCount > 0) {
492 msg << "Bike Statistics (avg of " << myBikeCount << "):\n"
493 << " RouteLength: " << getAvgBikeRouteLength() << "\n"
494 << " Speed: " << getAvgBikeTripSpeed() << "\n"
495 << " Duration: " << getAvgBikeDuration() << "\n"
496 << " WaitingTime: " << getAvgBikeWaitingTime() << "\n"
497 << " TimeLoss: " << getAvgBikeTimeLoss() << "\n"
498 << " DepartDelay: " << getAvgBikeDepartDelay() << "\n";
499 if (myVehicleCount > 0 && myWaitingDepartDelay >= 0) {
500 msg << "Statistics (avg of " << (myVehicleCount + myBikeCount) << "):\n";
501 }
502 }
503 if (myWaitingDepartDelay >= 0) {
504 msg << " DepartDelayWaiting: " << getAvgDepartDelayWaiting() << "\n";
505 }
506 if (myWalkCount > 0) {
507 msg << "Pedestrian Statistics (avg of " << myWalkCount << " walks):\n"
508 << " RouteLength: " << getAvgWalkRouteLength() << "\n"
509 << " Duration: " << getAvgWalkDuration() << "\n"
510 << " TimeLoss: " << getAvgWalkTimeLoss() << "\n";
511 }
512 printRideStatistics(msg, "Ride", "rides", 0);
513 printRideStatistics(msg, "Transport", "transports", 1);
514 return msg.str();
515}
516
517void
518MSDevice_Tripinfo::printRideStatistics(std::ostringstream& msg, const std::string& category, const std::string& modeName, const int index) {
519 if (myRideCount[index] > 0) {
520 msg << category << " Statistics (avg of " << myRideCount[index] << " " << modeName << "):\n";
521 msg << " WaitingTime: " << STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]) << "\n";
522 msg << " RouteLength: " << myTotalRideRouteLength[index] / myRideCount[index] << "\n";
523 msg << " Duration: " << STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]) << "\n";
524 if (myRideBusCount[index] > 0) {
525 msg << " Bus: " << myRideBusCount[index] << "\n";
526 }
527 if (myRideRailCount[index] > 0) {
528 msg << " Train: " << myRideRailCount[index] << "\n";
529 }
530 if (myRideTaxiCount[index] > 0) {
531 msg << " Taxi: " << myRideTaxiCount[index] << "\n";
532 }
533 if (myRideBikeCount[index] > 0) {
534 msg << " Bike: " << myRideBikeCount[index] << "\n";
535 }
536 if (myRideAbortCount[index] > 0) {
537 msg << " Aborted: " << myRideAbortCount[index] << "\n";
538 }
539 }
540
541}
542
543
544void
547 od.openTag("vehicleTripStatistics");
548 od.writeAttr("count", myVehicleCount);
549 od.writeAttr("routeLength", getAvgRouteLength());
550 od.writeAttr("speed", getAvgTripSpeed());
551 od.writeAttr("duration", getAvgDuration());
552 od.writeAttr("waitingTime", getAvgWaitingTime());
553 od.writeAttr("timeLoss", getAvgTimeLoss());
554 od.writeAttr("departDelay", getAvgDepartDelay());
555 od.writeAttr("departDelayWaiting", getAvgDepartDelayWaiting());
556 od.writeAttr("totalTravelTime", time2string(myTotalDuration));
558 od.closeTag();
559 if (myBikeCount > 0) {
560 od.openTag("bikeTripStatistics");
561 od.writeAttr("count", myBikeCount);
562 od.writeAttr("routeLength", getAvgBikeRouteLength());
563 od.writeAttr("speed", getAvgBikeTripSpeed());
564 od.writeAttr("duration", getAvgBikeDuration());
565 od.writeAttr("waitingTime", getAvgBikeWaitingTime());
566 od.writeAttr("timeLoss", getAvgBikeTimeLoss());
567 od.writeAttr("departDelay", getAvgBikeDepartDelay());
568 od.writeAttr("totalTravelTime", time2string(myTotalBikeDuration));
569 od.closeTag();
570 }
571 od.openTag("pedestrianStatistics");
572 od.writeAttr("number", myWalkCount);
573 od.writeAttr("routeLength", getAvgWalkRouteLength());
574 od.writeAttr("duration", getAvgWalkDuration());
575 od.writeAttr("timeLoss", getAvgWalkTimeLoss());
576 od.closeTag();
577 writeRideStatistics(od, "rideStatistics", 0);
578 writeRideStatistics(od, "transportStatistics", 1);
579}
580
581void
582MSDevice_Tripinfo::writeRideStatistics(OutputDevice& od, const std::string& category, const int index) {
583 od.openTag(category);
584 od.writeAttr("number", myRideCount[index]);
585 if (myRideCount[index] > 0) {
586 od.writeAttr("waitingTime", STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]));
587 od.writeAttr("routeLength", myTotalRideRouteLength[index] / myRideCount[index]);
588 od.writeAttr("duration", STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]));
589 od.writeAttr("bus", myRideBusCount[index]);
590 od.writeAttr("train", myRideRailCount[index]);
591 od.writeAttr("taxi", myRideTaxiCount[index]);
592 od.writeAttr("bike", myRideBikeCount[index]);
593 od.writeAttr("aborted", myRideAbortCount[index]);
594 }
595 od.closeTag();
596}
597
598
599double
601 if (myVehicleCount > 0) {
603 } else {
604 return 0;
605 }
606}
607
608double
610 if (myVehicleCount > 0) {
612 } else {
613 return 0;
614 }
615}
616
617double
619 if (myVehicleCount > 0) {
621 } else {
622 return 0;
623 }
624}
625
626double
628 if (myVehicleCount > 0) {
630 } else {
631 return 0;
632 }
633}
634
635
636double
638 if (myVehicleCount > 0) {
640 } else {
641 return 0;
642 }
643}
644
645
646double
648 if (myVehicleCount > 0) {
650 } else {
651 return 0;
652 }
653}
654
655double
657 if (myWaitingDepartDelay >= 0) {
659 } else {
660 return -1;
661 }
662}
663
664
665double
669
670double
672 if (myBikeCount > 0) {
674 } else {
675 return 0;
676 }
677}
678
679double
681 if (myBikeCount > 0) {
683 } else {
684 return 0;
685 }
686}
687
688double
690 if (myBikeCount > 0) {
692 } else {
693 return 0;
694 }
695}
696
697double
699 if (myBikeCount > 0) {
701 } else {
702 return 0;
703 }
704}
705
706
707double
709 if (myBikeCount > 0) {
711 } else {
712 return 0;
713 }
714}
715
716double
718 if (myBikeCount > 0) {
720 } else {
721 return 0;
722 }
723}
724
725
726double
730
731double
733 if (myWalkCount > 0) {
735 } else {
736 return 0;
737 }
738}
739
740double
742 if (myWalkCount > 0) {
744 } else {
745 return 0;
746 }
747}
748
749
750double
752 if (myWalkCount > 0) {
754 } else {
755 return 0;
756 }
757}
758
759
760double
762 if (myRideCount[0] > 0) {
764 } else {
765 return 0;
766 }
767}
768
769double
771 if (myRideCount[0] > 0) {
773 } else {
774 return 0;
775 }
776}
777
778double
780 if (myRideCount[0] > 0) {
781 return myTotalRideRouteLength[0] / myRideCount[0];
782 } else {
783 return 0;
784 }
785}
786
787
788std::string
789MSDevice_Tripinfo::getParameter(const std::string& key) const {
790 if (key == toString(SUMO_ATTR_WAITINGTIME)) {
792 } else if (key == toString(SUMO_ATTR_WAITINGCOUNT)) {
793 return toString(myWaitingCount);
794 } else if (key == toString(SUMO_ATTR_STOPTIME)) {
796 } else if (key == toString(SUMO_ATTR_ARRIVALTIME)) {
798 } else if (key == toString(SUMO_ATTR_ARRIVALLANE)) {
799 return toString(myArrivalLane);
800 } else if (key == toString(SUMO_ATTR_ARRIVALPOS)) {
801 return toString(myArrivalPos);
802 } else if (key == toString(SUMO_ATTR_ARRIVALPOS_LAT)) {
804 } else if (key == toString(SUMO_ATTR_ARRIVALSPEED)) {
805 return toString(myArrivalSpeed);
806 }
807 throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
808}
809
810
811std::string
812MSDevice_Tripinfo::getGlobalParameter(const std::string& prefixedKey) {
813 std::string key = prefixedKey; // by default, assume vehicleTripStatistics;
814 const std::string err = "Parameter '" + prefixedKey + "' is not supported for device of type 'tripinfo'";
815 if (StringUtils::startsWith(key, "vehicleTripStatistics.")) {
816 key = prefixedKey.substr(22);
817 } else if (StringUtils::startsWith(key, "bikeTripStatistics.")) {
818 key = prefixedKey.substr(19);
819 if (key == toString(SUMO_ATTR_COUNT)) {
820 return toString(myBikeCount);
821 } else if (key == "routeLength") {
823 } else if (key == toString(SUMO_ATTR_SPEED)) {
825 } else if (key == toString(SUMO_ATTR_DURATION)) {
827 } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
829 } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
831 } else if (key == "departDelay") {
833 } else if (key == "totalTravelTime") {
834 // avoid human readable output
836 }
837 throw InvalidArgument(err);
838
839 } else if (StringUtils::startsWith(key, "pedestrianStatistics.")) {
840 key = prefixedKey.substr(21);
841 if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
842 return toString(myWalkCount);
843 } else if (key == "routeLength") {
845 } else if (key == toString(SUMO_ATTR_DURATION)) {
847 } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
849 }
850 throw InvalidArgument(err);
851
852 } else if (StringUtils::startsWith(key, "rideStatistics.") ||
853 StringUtils::startsWith(key, "transportStatistics.")) {
854 int index = 0;
855 if (StringUtils::startsWith(key, "rideStatistics.")) {
856 key = prefixedKey.substr(15);
857 } else {
858 index = 1;
859 key = prefixedKey.substr(20);
860 }
861 if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
862 return toString(myRideCount[index]);
863 } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
864 return toString(STEPS2TIME(myTotalRideWaitingTime[index] / MAX2(1, myRideCount[index])));
865 } else if (key == "routeLength") {
866 return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
867 } else if (key == toString(SUMO_ATTR_DURATION)) {
868 return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
869 } else if (key == "bus") {
870 return toString(myRideBusCount[index]);
871 } else if (key == "train") {
872 return toString(myRideRailCount[index]);
873 } else if (key == "taxi") {
874 return toString(myRideTaxiCount[index]);
875 } else if (key == "bike") {
876 return toString(myRideBikeCount[index]);
877 } else if (key == "aborted") {
878 return toString(myRideAbortCount[index]);
879 }
880 throw InvalidArgument(err);
881 }
882 // vehicleTripStatistics
883 if (key == toString(SUMO_ATTR_COUNT)) {
884 return toString(myVehicleCount);
885 } else if (key == "routeLength") {
886 return toString(getAvgRouteLength());
887 } else if (key == toString(SUMO_ATTR_SPEED)) {
888 return toString(getAvgTripSpeed());
889 } else if (key == toString(SUMO_ATTR_DURATION)) {
890 return toString(getAvgDuration());
891 } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
892 return toString(getAvgWaitingTime());
893 } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
894 return toString(getAvgTimeLoss());
895 } else if (key == "departDelay") {
896 return toString(getAvgDepartDelay());
897 } else if (key == "departDelayWaiting") {
899 } else if (key == "totalTravelTime") {
900 // avoid human readable output
902 } else if (key == "totalDepartDelay") {
904 }
905 throw InvalidArgument(err);
906}
907
908
909void
911 // always write device id to replicate stochastic assignment
914 if (myHolder.hasDeparted()) {
915 std::ostringstream internals;
916 internals << myDepartLane << " ";
918 internals << myDepartPosLat << " ";
919 }
920 std::string state_arrivalLane = myArrivalLane == "" ? STATE_EMPTY_ARRIVALLANE : myArrivalLane;
921 internals << myDepartSpeed << " " << myRouteLength << " " << myWaitingTime << " " << myAmWaiting << " " << myWaitingCount << " ";
922 internals << myStoppingTime << " " << myParkingStarted << " ";
923 internals << myArrivalTime << " " << state_arrivalLane << " " << myArrivalPos << " " << myArrivalPosLat << " " << myArrivalSpeed;
924 out.writeAttr(SUMO_ATTR_STATE, internals.str());
925 }
926 out.closeTag();
927}
928
929
930void
932 if (attrs.hasAttribute(SUMO_ATTR_STATE)) {
933 std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
934 bis >> myDepartLane;
936 bis >> myDepartPosLat;
937 }
942 myArrivalLane = "";
943 }
944 }
945}
946
947
948/****************************************************************************/
long long int SUMOTime
Definition GUI.h:36
#define NOT_ARRIVED
#define STATE_EMPTY_ARRIVALLANE
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 STEPS2TIME(x)
Definition SUMOTime.h:58
#define SIMSTEP
Definition SUMOTime.h:64
#define TIME2STEPS(x)
Definition SUMOTime.h:60
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TAXI
vehicle is a taxi
@ GIVEN
The time is given.
@ SUMO_TAG_DEVICE
@ SUMO_ATTR_NUMBER
@ SUMO_ATTR_ARRIVALSPEED
@ SUMO_ATTR_ARRIVALLANE
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_ARRIVALTIME
@ SUMO_ATTR_WAITINGTIME
@ SUMO_ATTR_ARRIVALPOS
@ SUMO_ATTR_STOPTIME
@ SUMO_ATTR_TIMELOSS
@ SUMO_ATTR_WAITINGCOUNT
@ SUMO_ATTR_ID
@ SUMO_ATTR_ARRIVALPOS_LAT
@ SUMO_ATTR_DURATION
@ SUMO_ATTR_COUNT
@ SUMO_ATTR_STATE
The state of a link.
int gPrecision
the precision for floating point outputs
Definition StdDefs.cpp:27
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition StdDefs.h:62
T MAX2(T a, T b)
Definition StdDefs.h:86
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
A device which collects info on the vehicle trip (mainly on departure and arrival)
bool notifyEnter(SUMOTrafficObject &veh, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Saves departure info on insertion.
static SUMOTime myTotalDepartDelay
const std::string deviceName() const
return the name for this type of device
double myDepartSpeed
The speed on departure.
static std::vector< int > myRideAbortCount
static double getAvgBikeTripSpeed()
static std::vector< SUMOTime > myTotalRideWaitingTime
static void writeStatistics(OutputDevice &od)
write statistic output to (xml) file
void saveState(OutputDevice &out) const
Saves the state of the device.
SUMOTime myArrivalTime
The vehicle's arrival time.
SUMOTime myWaitingTime
The overall waiting time.
void loadState(const SUMOSAXAttributes &attrs)
Loads the state of the device from the given description.
static std::set< const MSDevice_Tripinfo *, ComparatorNumericalIdLess > myPendingOutput
devices which may still need to produce output
static SUMOTime myTotalBikeDuration
static SUMOTime myTotalWalkTimeLoss
static double getAvgRideWaitingTime()
SUMOTime myParkingStarted
The time when parking started.
static double getAvgBikeDuration()
static double getAvgWalkRouteLength()
std::string myArrivalLane
The lane the vehicle arrived at.
static double getAvgDepartDelayWaiting()
MSDevice_Tripinfo(SUMOVehicle &holder, const std::string &id)
Constructor.
static double getAvgTimeLoss()
static void printRideStatistics(std::ostringstream &msg, const std::string &category, const std::string &modeName, const int index)
double myArrivalSpeed
The speed when arriving.
static double getAvgRideRouteLength()
static double getAvgBikeTimeLoss()
~MSDevice_Tripinfo()
Destructor.
static SUMOTime myTotalTimeLoss
static double getTotalDepartDelay()
static double getAvgRideDuration()
static std::vector< int > myRideRailCount
static double getAvgDepartDelay()
static double myTotalBikeRouteLength
static double myTotalSpeed
static double getAvgBikeRouteLength()
static std::vector< SUMOTime > myTotalRideDuration
static SUMOTime myTotalBikeTimeLoss
static double getAvgTripSpeed()
static std::string getGlobalParameter(const std::string &prefixedKey)
try to retrieve the given parameter from the global statistics. Throw exception for unsupported key
static double getAvgRouteLength()
accessors for GUINet-Parameters
void updateParkingStopTime()
update stopping time after parking
static SUMOTime myTotalBikeDepartDelay
static SUMOTime myTotalDuration
static SUMOTime myTotalWalkDuration
static std::string printStatistics()
get statistics for printing to stdout
static void generateOutputForUnfinished()
generate output for vehicles which are still in the network
static double myTotalBikeSpeed
static double getAvgWaitingTime()
static double getTotalBikeDepartDelay()
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, see MSMoveReminder::notifyMoveInternal()
static void addPedestrianData(double walkLength, SUMOTime walkDuration, SUMOTime walkTimeLoss)
record tripinfo data for pedestrians
bool notifyMove(SUMOTrafficObject &veh, double oldPos, double newPos, double newSpeed)
Checks for waiting steps when the vehicle moves.
std::string myDepartLane
The lane the vehicle departed at.
static void buildVehicleDevices(SUMOVehicle &v, std::vector< MSVehicleDevice * > &into)
Build devices for the given vehicle, if needed.
static void writeRideStatistics(OutputDevice &od, const std::string &category, const int index)
double myRouteLength
The route length.
static SUMOTime myTotalWaitingTime
static double myTotalRouteLength
static double getAvgBikeWaitingTime()
double myArrivalPosLat
The lateral position on the lane the vehicle arrived at.
static double getAvgDuration()
static SUMOTime myTotalBikeWaitingTime
static bool lowAcceleration(const SUMOTrafficObject &veh)
static void cleanup()
resets counters
int myWaitingCount
The overall number of unintended stops.
SUMOTime myStoppingTime
The overall intentional stopping time.
bool notifyLeave(SUMOTrafficObject &veh, double lastPos, MSMoveReminder::Notification reason, const MSLane *enteredLane=0)
Saves arrival info.
void generateOutput(OutputDevice *tripinfoOut) const
Called on writing tripinfo output.
static void addRideTransportData(const bool isPerson, const double distance, const SUMOTime duration, const SUMOVehicleClass vClass, const std::string &line, const SUMOTime waitingTime)
record tripinfo data for rides and transports
static std::vector< int > myRideCount
bool notifyIdle(SUMOTrafficObject &veh)
record idling as waiting time - cf issue 2233
static double getAvgWalkDuration()
SUMOTime myMesoTimeLoss
The time loss when compared to the desired and allowed speed.
static std::vector< int > myRideBusCount
double myDepartPosLat
The lateral depart position.
bool myAmWaiting
Whether the vehicle is currently waiting.
static int myUndepartedVehicleCount
static int myVehicleCount
global tripinfo statistics
double myArrivalPos
The position on the lane the vehicle arrived at.
static std::vector< int > myRideTaxiCount
static std::vector< int > myRideBikeCount
static int myBikeCount
separate values for bicycles
MSMoveReminder::Notification myArrivalReason
The reason for vehicle arrival.
static double getAvgWalkTimeLoss()
static double myTotalWalkRouteLength
static void insertOptions(OptionsCont &oc)
Inserts MSDevice_Tripinfo-options.
std::string getParameter(const std::string &key) const
try to retrieve the given parameter from this device. Throw exception for unsupported key
static SUMOTime myWaitingDepartDelay
static std::vector< double > myTotalRideRouteLength
static double getAvgBikeDepartDelay()
A device which collects info on the vehicle trip (mainly on departure and arrival)
static void insertDefaultAssignmentOptions(const std::string &deviceName, const std::string &optionsTopic, OptionsCont &oc, const bool isPerson=false)
Adds common command options that allow to assign devices to vehicles.
Definition MSDevice.cpp:157
static bool equippedByDefaultAssignmentOptions(const OptionsCont &oc, const std::string &deviceName, DEVICEHOLDER &v, bool outputOptionSet, const bool isPerson=false)
Determines whether a vehicle should get a certain device.
Definition MSDevice.h:200
double getLength() const
return the length of the edge
Definition MSEdge.h:694
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition MSEdge.cpp:1198
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false, int routingMode=0) const
Definition MSEdge.cpp:753
static bool gUseMesoSim
Definition MSGlobals.h:106
static double gLateralResolution
Definition MSGlobals.h:100
Representation of a lane in the micro simulation.
Definition MSLane.h:84
double getLength() const
Returns the lane's length.
Definition MSLane.h:617
Something on a lane to be noticed about vehicle movement.
Notification
Definition of a vehicle state.
@ NOTIFICATION_VAPORIZED_TRACI
The vehicle got removed via TraCI.
@ NOTIFICATION_ARRIVED
The vehicle arrived at its destination (is deleted)
@ NOTIFICATION_TELEPORT_ARRIVED
The vehicle was teleported out of the net.
@ NOTIFICATION_VAPORIZED_CALIBRATOR
The vehicle got removed by a calibrator.
@ NOTIFICATION_VAPORIZED_GUI
The vehicle got removed via the GUI.
@ NOTIFICATION_DEPARTED
The vehicle has departed (was inserted into the network)
@ NOTIFICATION_VAPORIZED_VAPORIZER
The vehicle got vaporized with a vaporizer.
@ NOTIFICATION_JUNCTION
The vehicle arrived at a junction.
@ NOTIFICATION_PARKING
The vehicle starts or ends parking.
@ NOTIFICATION_VAPORIZED_COLLISION
The vehicle got removed by a collision.
@ NOTIFICATION_TELEPORT
The vehicle is being teleported.
@ NOTIFICATION_TELEPORT_CONTINUATION
The vehicle continues being teleported past an edge.
const MSLane * getLane() const
Returns the lane the reminder works on.
The simulated network and simulation perfomer.
Definition MSNet.h:89
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition MSNet.cpp:187
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition MSNet.h:334
bool hasPersons() const
Returns whether persons are simulated.
Definition MSNet.h:409
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition MSNet.cpp:1262
const MSEdge * getLastEdge() const
returns the destination edge
Definition MSRoute.cpp:91
void eraseAll()
@removes all transportables
Abstract in-vehicle device.
SUMOVehicle & myHolder
The vehicle that stores the device.
Representation of a vehicle in the micro simulation.
Definition MSVehicle.h:77
double accelThresholdForWaiting() const
maximum acceleration to consider a vehicle as 'waiting' at low speed
Definition MSVehicle.h:2089
double getAcceleration() const
Returns the vehicle's acceleration in m/s (this is computed as the last step's mean acceleration in c...
Definition MSVehicle.h:514
const std::string & getID() const
Returns the name of the vehicle type.
const std::string & getID() const
Returns the id.
Definition Named.h:74
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void addOptionSubTopic(const std::string &topic)
Adds an option subtopic.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
static OutputDevice & getDeviceByOption(const std::string &name)
Returns the device described by the option.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
void setPrecision(int precision=gPrecision)
Sets the precision or resets it to default.
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
virtual const MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual double getChosenSpeedFactor() const =0
virtual double getSpeed() const =0
Returns the object's current speed.
virtual SUMOTime getWaitingTime(const bool accumulated=false) const =0
virtual bool isStopped() const =0
Returns whether the object is at a stop.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual int getRoutePosition() const =0
return index of edge within route
virtual const MSEdge * getEdge() const =0
Returns the edge the object is currently at.
virtual double getPositionOnLane() const =0
Get the object's position along the lane.
Representation of a vehicle.
Definition SUMOVehicle.h:63
virtual SUMOTime getDeparture() const =0
Returns this vehicle's real departure time.
virtual const std::vector< MSVehicleDevice * > & getDevices() const =0
Returns this vehicle's devices.
virtual bool hasDeparted() const =0
Returns whether this vehicle has departed.
virtual int getNumberReroutes() const =0
Returns the number of new routes this vehicle got.
virtual double getArrivalPos() const =0
Returns this vehicle's desired arrivalPos for its current route (may change on reroute)
virtual double getDepartPos() const =0
Returns this vehicle's real departure position.
virtual SUMOTime getDepartDelay() const =0
virtual const MSRoute & getRoute() const =0
Returns the current route.
Structure representing possible vehicle parameter.
DepartDefinition departProcedure
Information how the vehicle shall choose the depart time.
int arrivalEdge
(optional) The final edge within the route of the vehicle
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.