Eclipse SUMO - Simulation of Urban MObility
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-2024 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 // ===========================================================================
45 std::set<const MSDevice_Tripinfo*, ComparatorNumericalIdLess> MSDevice_Tripinfo::myPendingOutput;
46 
56 
63 
68 std::vector<int> MSDevice_Tripinfo::myRideCount({0, 0});
69 std::vector<int> MSDevice_Tripinfo::myRideBusCount({0, 0});
70 std::vector<int> MSDevice_Tripinfo::myRideRailCount({0, 0});
71 std::vector<int> MSDevice_Tripinfo::myRideTaxiCount({0, 0});
72 std::vector<int> MSDevice_Tripinfo::myRideBikeCount({0, 0});
73 std::vector<int> MSDevice_Tripinfo::myRideAbortCount({0, 0});
74 std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideWaitingTime({0, 0});
75 std::vector<double> MSDevice_Tripinfo::myTotalRideRouteLength({0., 0.});
76 std::vector<SUMOTime> MSDevice_Tripinfo::myTotalRideDuration({0, 0});
77 
78 // ===========================================================================
79 // method definitions
80 // ===========================================================================
81 // ---------------------------------------------------------------------------
82 // static initialisation methods
83 // ---------------------------------------------------------------------------
84 void
86  oc.addOptionSubTopic("Tripinfo Device");
87  insertDefaultAssignmentOptions("tripinfo", "Tripinfo Device", oc);
88 }
89 
90 
91 void
92 MSDevice_Tripinfo::buildVehicleDevices(SUMOVehicle& v, std::vector<MSVehicleDevice*>& into) {
94  const bool enableByOutputOption = oc.isSet("tripinfo-output") || oc.getBool("duration-log.statistics");
95  if (equippedByDefaultAssignmentOptions(oc, "tripinfo", v, enableByOutputOption)) {
96  MSDevice_Tripinfo* device = new MSDevice_Tripinfo(v, "tripinfo_" + v.getID());
97  into.push_back(device);
98  myPendingOutput.insert(device);
99  }
100 }
101 
102 
103 // ---------------------------------------------------------------------------
104 // MSDevice_Tripinfo-methods
105 // ---------------------------------------------------------------------------
106 MSDevice_Tripinfo::MSDevice_Tripinfo(SUMOVehicle& holder, const std::string& id) :
107  MSVehicleDevice(holder, id),
108  myDepartLane(""),
109  myDepartSpeed(-1),
110  myDepartPosLat(0),
111  myWaitingTime(0),
112  myAmWaiting(false),
113  myWaitingCount(0),
114  myStoppingTime(0),
115  myParkingStarted(-1),
116  myArrivalTime(NOT_ARRIVED),
117  myArrivalLane(""),
118  myArrivalPos(-1),
119  myArrivalPosLat(0.),
120  myArrivalSpeed(-1),
121  myArrivalReason(MSMoveReminder::NOTIFICATION_ARRIVED),
122  myMesoTimeLoss(0),
123  myRouteLength(0.) {
124 }
125 
126 
128  // ensure clean up for vaporized vehicles which do not generate output
129  myPendingOutput.erase(this);
130 }
131 
132 void
134  myVehicleCount = 0;
135  myTotalRouteLength = 0;
136  myTotalSpeed = 0;
137  myTotalDuration = 0;
138  myTotalWaitingTime = 0;
139  myTotalTimeLoss = 0;
140  myTotalDepartDelay = 0;
142 
143  myBikeCount = 0;
145  myTotalBikeSpeed = 0;
149 
150  myWalkCount = 0;
154 
155  myRideCount = {0, 0};
156  myRideBusCount = {0, 0};
157  myRideRailCount = {0, 0};
158  myRideTaxiCount = {0, 0};
159  myRideBikeCount = {0, 0};
160  myRideAbortCount = {0, 0};
161  myTotalRideWaitingTime = {0, 0};
162  myTotalRideRouteLength = {0., 0.};
163  myTotalRideDuration = {0, 0};
164 }
165 
166 bool
168  if (veh.isVehicle()) {
170  if (!myAmWaiting) {
171  myWaitingCount++;
172  myAmWaiting = true;
173  }
174  }
175  return true;
176 }
177 
178 
179 bool
181  double /*newPos*/, double newSpeed) {
182  if (veh.isStopped()) {
183  if (newSpeed <= SUMO_const_haltingSpeed) {
185  }
186  } else if (newSpeed <= SUMO_const_haltingSpeed && lowAcceleration(veh)) {
188  if (!myAmWaiting) {
189  myWaitingCount++;
190  myAmWaiting = true;
191  }
192  } else {
193  myAmWaiting = false;
194  }
195  return true;
196 }
197 
198 
199 bool
202  // acceleration is not modelled
203  return false;
204  } else {
205  const MSVehicle& v = dynamic_cast<const MSVehicle&>(veh);
206  return v.getAcceleration() <= v.accelThresholdForWaiting();
207  }
208 }
209 
210 
211 void
213  const double /* frontOnLane */,
214  const double timeOnLane,
215  const double /* meanSpeedFrontOnLane */,
216  const double meanSpeedVehicleOnLane,
217  const double /* travelledDistanceFrontOnLane */,
218  const double /* travelledDistanceVehicleOnLane */,
219  const double /* meanLengthOnLane */) {
220 
221  // called by meso
222  const double vmax = veh.getEdge()->getVehicleMaxSpeed(&veh);
223  if (vmax > 0) {
224  myMesoTimeLoss += TIME2STEPS(timeOnLane * (vmax - meanSpeedVehicleOnLane) / vmax);
225  }
226  myWaitingTime += veh.getWaitingTime();
227 }
228 
229 
230 void
232  if (myParkingStarted >= 0) {
234  myParkingStarted = -1;
235  }
236 }
237 
238 bool
241  if (!MSGlobals::gUseMesoSim) {
242  myDepartLane = static_cast<MSVehicle&>(veh).getLane()->getID();
243  myDepartPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
244  } else {
245  myDepartLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
246  }
247  myDepartSpeed = veh.getSpeed();
249  } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
250  // notifyMove is not called while parking
251  // @note insertion delay when resuming after parking is included
253  }
254  return true;
255 }
256 
257 
258 bool
260  MSMoveReminder::Notification reason, const MSLane* /* enteredLane */) {
261  if (reason >= MSMoveReminder::NOTIFICATION_ARRIVED) {
263  myArrivalReason = reason;
264  if (!MSGlobals::gUseMesoSim) {
265  myArrivalLane = static_cast<MSVehicle&>(veh).getLane()->getID();
266  myArrivalPosLat = static_cast<MSVehicle&>(veh).getLateralPositionOnLane();
267  } else {
268  myArrivalLane = veh.getEdge()->getFirstAllowed(veh.getVClass(), true)->getID();
269  }
270  // @note vehicle may have moved past its arrivalPos during the last step
271  // due to non-zero arrivalspeed but we consider it as arrived at the desired position
272  // However, vaporization may happen anywhere (via TraCI)
274  // vaporized
276  } else {
278  }
279  myArrivalSpeed = veh.getSpeed();
281  } else if (reason == MSMoveReminder::NOTIFICATION_PARKING) {
283  } else if (reason == NOTIFICATION_JUNCTION
284  || reason == NOTIFICATION_TELEPORT
285  || reason == NOTIFICATION_TELEPORT_CONTINUATION) {
288  } else {
289  const MSLane* lane = static_cast<MSVehicle&>(veh).getLane();
290  if (lane != nullptr) {
291  myRouteLength += lane->getLength();
292  }
293  }
294  }
295  return true;
296 }
297 
298 
299 void
301  const SUMOTime timeLoss = MSGlobals::gUseMesoSim ? myMesoTimeLoss : static_cast<MSVehicle&>(myHolder).getTimeLoss();
302  const double routeLength = myRouteLength + (myArrivalTime == NOT_ARRIVED ? myHolder.getPositionOnLane() : myArrivalPos);
303  SUMOTime duration = 0;
304  if (myHolder.hasDeparted()) {
306  if (myHolder.getVClass() == SVC_BICYCLE) {
307  myBikeCount++;
308  myTotalBikeRouteLength += routeLength;
309  myTotalBikeSpeed += routeLength / STEPS2TIME(duration);
310  myTotalBikeDuration += duration;
312  myTotalBikeTimeLoss += timeLoss;
313  } else {
314  myVehicleCount++;
315  myTotalRouteLength += routeLength;
316  myTotalSpeed += routeLength / STEPS2TIME(duration);
317  myTotalDuration += duration;
319  myTotalTimeLoss += timeLoss;
320  }
322  }
323 
324  myPendingOutput.erase(this);
325  if (tripinfoOut == nullptr) {
326  return;
327  }
328  // write
329  OutputDevice& os = *tripinfoOut;
330  os.openTag("tripinfo").writeAttr("id", myHolder.getID());
331  os.writeAttr("depart", myHolder.hasDeparted() ? time2string(myHolder.getDeparture()) : "-1");
332  os.writeAttr("departLane", myDepartLane);
333  os.writeAttr("departPos", myHolder.getDepartPos());
335  os.writeAttr("departPosLat", myDepartPosLat);
336  }
337  os.writeAttr("departSpeed", myDepartSpeed);
338  SUMOTime departDelay = myHolder.getDepartDelay();
339  const SUMOVehicleParameter& param = myHolder.getParameter();
340  if (!myHolder.hasDeparted()) {
341  assert(param.depart <= SIMSTEP || param.departProcedure != DepartDefinition::GIVEN);
342  departDelay = SIMSTEP - param.depart;
343  }
344  os.writeAttr("departDelay", time2string(departDelay));
345  os.writeAttr("arrival", time2string(myArrivalTime));
346  os.writeAttr("arrivalLane", myArrivalLane);
347  os.writeAttr("arrivalPos", myArrivalPos);
349  os.writeAttr("arrivalPosLat", myArrivalPosLat);
350  }
351  os.writeAttr("arrivalSpeed", myArrivalSpeed);
352  os.writeAttr("duration", time2string(duration));
353  os.writeAttr("routeLength", routeLength);
358  os.writeAttr("rerouteNo", myHolder.getNumberReroutes());
359  os.writeAttr("devices", toString(myHolder.getDevices()));
360  os.writeAttr("vType", myHolder.getVehicleType().getID());
361  os.writeAttr("speedFactor", myHolder.getChosenSpeedFactor());
362  std::string vaporized;
363  switch (myArrivalReason) {
365  vaporized = "calibrator";
366  break;
368  vaporized = "gui";
369  break;
371  vaporized = "collision";
372  break;
374  vaporized = "vaporizer";
375  break;
377  vaporized = "traci";
378  break;
380  vaporized = "teleport";
381  break;
382  default:
384  (param.arrivalEdge >= 0 && myHolder.getRoutePosition() >= param.arrivalEdge)) {
385  vaporized = "";
386  } else {
387  vaporized = "end";
388  }
389  break;
390  }
391  os.writeAttr("vaporized", vaporized);
392  // cannot close tag because emission device output might follow
393 }
394 
395 
396 void
398  MSNet* net = MSNet::getInstance();
399  OutputDevice* tripinfoOut = (OptionsCont::getOptions().isSet("tripinfo-output") ?
400  &OutputDevice::getDeviceByOption("tripinfo-output") : nullptr);
403  const bool writeUndeparted = OptionsCont::getOptions().getBool("tripinfo-output.write-undeparted");
404  const SUMOTime t = net->getCurrentTimeStep();
405  while (myPendingOutput.size() > 0) {
406  const MSDevice_Tripinfo* d = *myPendingOutput.begin();
407  const bool departed = d->myHolder.hasDeparted();
408  const bool departDelayed = d->myHolder.getParameter().depart <= t;
409  if (!departed && departDelayed) {
412  }
413  if (departed || (writeUndeparted && departDelayed)) {
414  const_cast<MSDevice_Tripinfo*>(d)->updateParkingStopTime();
415  d->generateOutput(tripinfoOut);
416  if (tripinfoOut != nullptr) {
417  for (MSVehicleDevice* const dev : d->myHolder.getDevices()) {
418  if (typeid(*dev) == typeid(MSDevice_Tripinfo) || typeid(*dev) == typeid(MSDevice_Vehroutes)) {
419  // tripinfo is special and vehroute has its own write-unfinished option
420  continue;
421  }
422  dev->generateOutput(tripinfoOut);
423  }
424  OutputDevice::getDeviceByOption("tripinfo-output").closeTag();
425  }
426  } else {
427  myPendingOutput.erase(d);
428  }
429  }
430  // unfinished persons
431  if (net->hasPersons()) {
433  while (pc.loadedBegin() != pc.loadedEnd()) {
434  pc.erase(pc.loadedBegin()->second);
435  }
436  }
437 
438 }
439 
440 
441 void
442 MSDevice_Tripinfo::addPedestrianData(double walkLength, SUMOTime walkDuration, SUMOTime walkTimeLoss) {
443  myWalkCount++;
444  myTotalWalkRouteLength += walkLength;
445  myTotalWalkDuration += walkDuration;
446  myTotalWalkTimeLoss += walkTimeLoss;
447 }
448 
449 
450 void
451 MSDevice_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 
477 std::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  }
490  if (myBikeCount > 0) {
491  msg << "Bike Statistics (avg of " << myBikeCount << "):\n"
492  << " RouteLength: " << getAvgBikeRouteLength() << "\n"
493  << " Speed: " << getAvgBikeTripSpeed() << "\n"
494  << " Duration: " << getAvgBikeDuration() << "\n"
495  << " WaitingTime: " << getAvgBikeWaitingTime() << "\n"
496  << " TimeLoss: " << getAvgBikeTimeLoss() << "\n";
497  if (myVehicleCount > 0) {
498  msg << "Statistics (avg of " << (myVehicleCount + myBikeCount) << "):\n";
499  }
500  }
501  msg << " DepartDelay: " << getAvgDepartDelay() << "\n";
502  if (myWaitingDepartDelay >= 0) {
503  msg << " DepartDelayWaiting: " << getAvgDepartDelayWaiting() << "\n";
504  }
505  if (myWalkCount > 0) {
506  msg << "Pedestrian Statistics (avg of " << myWalkCount << " walks):\n"
507  << " RouteLength: " << getAvgWalkRouteLength() << "\n"
508  << " Duration: " << getAvgWalkDuration() << "\n"
509  << " TimeLoss: " << getAvgWalkTimeLoss() << "\n";
510  }
511  printRideStatistics(msg, "Ride", "rides", 0);
512  printRideStatistics(msg, "Transport", "transports", 1);
513  return msg.str();
514 }
515 
516 void
517 MSDevice_Tripinfo::printRideStatistics(std::ostringstream& msg, const std::string& category, const std::string& modeName, const int index) {
518  if (myRideCount[index] > 0) {
519  msg << category << " Statistics (avg of " << myRideCount[index] << " " << modeName << "):\n";
520  msg << " WaitingTime: " << STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]) << "\n";
521  msg << " RouteLength: " << myTotalRideRouteLength[index] / myRideCount[index] << "\n";
522  msg << " Duration: " << STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]) << "\n";
523  if (myRideBusCount[index] > 0) {
524  msg << " Bus: " << myRideBusCount[index] << "\n";
525  }
526  if (myRideRailCount[index] > 0) {
527  msg << " Train: " << myRideRailCount[index] << "\n";
528  }
529  if (myRideTaxiCount[index] > 0) {
530  msg << " Taxi: " << myRideTaxiCount[index] << "\n";
531  }
532  if (myRideBikeCount[index] > 0) {
533  msg << " Bike: " << myRideBikeCount[index] << "\n";
534  }
535  if (myRideAbortCount[index] > 0) {
536  msg << " Aborted: " << myRideAbortCount[index] << "\n";
537  }
538  }
539 
540 }
541 
542 
543 void
546  od.openTag("vehicleTripStatistics");
547  od.writeAttr("count", myVehicleCount);
548  od.writeAttr("routeLength", getAvgRouteLength());
549  od.writeAttr("speed", getAvgTripSpeed());
550  od.writeAttr("duration", getAvgDuration());
551  od.writeAttr("waitingTime", getAvgWaitingTime());
552  od.writeAttr("timeLoss", getAvgTimeLoss());
553  od.writeAttr("departDelay", getAvgDepartDelay());
554  od.writeAttr("departDelayWaiting", getAvgDepartDelayWaiting());
555  od.writeAttr("totalTravelTime", time2string(myTotalDuration));
556  od.writeAttr("totalDepartDelay", time2string(TIME2STEPS(getTotalDepartDelay())));
557  od.closeTag();
558  if (myBikeCount > 0) {
559  od.openTag("bikeTripStatistics");
560  od.writeAttr("count", myBikeCount);
561  od.writeAttr("routeLength", getAvgBikeRouteLength());
562  od.writeAttr("speed", getAvgBikeTripSpeed());
563  od.writeAttr("duration", getAvgBikeDuration());
564  od.writeAttr("waitingTime", getAvgBikeWaitingTime());
565  od.writeAttr("timeLoss", getAvgBikeTimeLoss());
566  od.writeAttr("totalTravelTime", time2string(myTotalBikeDuration));
567  od.closeTag();
568  }
569  od.openTag("pedestrianStatistics");
570  od.writeAttr("number", myWalkCount);
571  od.writeAttr("routeLength", getAvgWalkRouteLength());
572  od.writeAttr("duration", getAvgWalkDuration());
573  od.writeAttr("timeLoss", getAvgWalkTimeLoss());
574  od.closeTag();
575  writeRideStatistics(od, "rideStatistics", 0);
576  writeRideStatistics(od, "transportStatistics", 1);
577 }
578 
579 void
580 MSDevice_Tripinfo::writeRideStatistics(OutputDevice& od, const std::string& category, const int index) {
581  od.openTag(category);
582  od.writeAttr("number", myRideCount[index]);
583  if (myRideCount[index] > 0) {
584  od.writeAttr("waitingTime", STEPS2TIME(myTotalRideWaitingTime[index] / myRideCount[index]));
585  od.writeAttr("routeLength", myTotalRideRouteLength[index] / myRideCount[index]);
586  od.writeAttr("duration", STEPS2TIME(myTotalRideDuration[index] / myRideCount[index]));
587  od.writeAttr("bus", myRideBusCount[index]);
588  od.writeAttr("train", myRideRailCount[index]);
589  od.writeAttr("taxi", myRideTaxiCount[index]);
590  od.writeAttr("bike", myRideBikeCount[index]);
591  od.writeAttr("aborted", myRideAbortCount[index]);
592  }
593  od.closeTag();
594 }
595 
596 
597 double
599  if (myVehicleCount > 0) {
601  } else {
602  return 0;
603  }
604 }
605 
606 double
608  if (myVehicleCount > 0) {
609  return myTotalSpeed / myVehicleCount;
610  } else {
611  return 0;
612  }
613 }
614 
615 double
617  if (myVehicleCount > 0) {
619  } else {
620  return 0;
621  }
622 }
623 
624 double
626  if (myVehicleCount > 0) {
628  } else {
629  return 0;
630  }
631 }
632 
633 
634 double
636  if (myVehicleCount > 0) {
638  } else {
639  return 0;
640  }
641 }
642 
643 
644 double
646  if (myVehicleCount > 0) {
648  } else {
649  return 0;
650  }
651 }
652 
653 double
655  if (myWaitingDepartDelay >= 0) {
657  } else {
658  return -1;
659  }
660 }
661 
662 
663 double
666 }
667 
668 double
670  if (myBikeCount > 0) {
672  } else {
673  return 0;
674  }
675 }
676 
677 double
679  if (myBikeCount > 0) {
680  return myTotalBikeSpeed / myBikeCount;
681  } else {
682  return 0;
683  }
684 }
685 
686 double
688  if (myBikeCount > 0) {
690  } else {
691  return 0;
692  }
693 }
694 
695 double
697  if (myBikeCount > 0) {
699  } else {
700  return 0;
701  }
702 }
703 
704 
705 double
707  if (myBikeCount > 0) {
709  } else {
710  return 0;
711  }
712 }
713 
714 
715 
716 double
718  if (myWalkCount > 0) {
720  } else {
721  return 0;
722  }
723 }
724 
725 double
727  if (myWalkCount > 0) {
729  } else {
730  return 0;
731  }
732 }
733 
734 
735 double
737  if (myWalkCount > 0) {
739  } else {
740  return 0;
741  }
742 }
743 
744 
745 double
747  if (myRideCount[0] > 0) {
749  } else {
750  return 0;
751  }
752 }
753 
754 double
756  if (myRideCount[0] > 0) {
758  } else {
759  return 0;
760  }
761 }
762 
763 double
765  if (myRideCount[0] > 0) {
766  return myTotalRideRouteLength[0] / myRideCount[0];
767  } else {
768  return 0;
769  }
770 }
771 
772 
773 std::string
774 MSDevice_Tripinfo::getParameter(const std::string& key) const {
775  if (key == toString(SUMO_ATTR_WAITINGTIME)) {
777  } else if (key == toString(SUMO_ATTR_WAITINGCOUNT)) {
778  return toString(myWaitingCount);
779  } else if (key == toString(SUMO_ATTR_STOPTIME)) {
781  } else if (key == toString(SUMO_ATTR_ARRIVALTIME)) {
783  } else if (key == toString(SUMO_ATTR_ARRIVALLANE)) {
784  return toString(myArrivalLane);
785  } else if (key == toString(SUMO_ATTR_ARRIVALPOS)) {
786  return toString(myArrivalPos);
787  } else if (key == toString(SUMO_ATTR_ARRIVALPOS_LAT)) {
788  return toString(myArrivalPosLat);
789  } else if (key == toString(SUMO_ATTR_ARRIVALSPEED)) {
790  return toString(myArrivalSpeed);
791  }
792  throw InvalidArgument("Parameter '" + key + "' is not supported for device of type '" + deviceName() + "'");
793 }
794 
795 
796 std::string
797 MSDevice_Tripinfo::getGlobalParameter(const std::string& prefixedKey) {
798  std::string key = prefixedKey; // by default, assume vehicleTripStatistics;
799  const std::string err = "Parameter '" + prefixedKey + "' is not supported for device of type 'tripinfo'";
800  if (StringUtils::startsWith(key, "vehicleTripStatistics.")) {
801  key = prefixedKey.substr(22);
802  } else if (StringUtils::startsWith(key, "bikeTripStatistics.")) {
803  key = prefixedKey.substr(19);
804  if (key == toString(SUMO_ATTR_COUNT)) {
805  return toString(myBikeCount);
806  } else if (key == "routeLength") {
808  } else if (key == toString(SUMO_ATTR_SPEED)) {
809  return toString(getAvgBikeTripSpeed());
810  } else if (key == toString(SUMO_ATTR_DURATION)) {
811  return toString(getAvgBikeDuration());
812  } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
814  } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
815  return toString(getAvgBikeTimeLoss());
816  } else if (key == "totalTravelTime") {
817  // avoid human readable output
819  }
820  throw InvalidArgument(err);
821 
822  } else if (StringUtils::startsWith(key, "pedestrianStatistics.")) {
823  key = prefixedKey.substr(21);
824  if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
825  return toString(myWalkCount);
826  } else if (key == "routeLength") {
828  } else if (key == toString(SUMO_ATTR_DURATION)) {
829  return toString(getAvgWalkDuration());
830  } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
831  return toString(getAvgWalkTimeLoss());
832  }
833  throw InvalidArgument(err);
834 
835  } else if (StringUtils::startsWith(key, "rideStatistics.") ||
836  StringUtils::startsWith(key, "transportStatistics.")) {
837  int index = 0;
838  if (StringUtils::startsWith(key, "rideStatistics.")) {
839  key = prefixedKey.substr(15);
840  } else {
841  index = 1;
842  key = prefixedKey.substr(20);
843  }
844  if (key == toString(SUMO_ATTR_NUMBER) || key == toString(SUMO_ATTR_COUNT)) {
845  return toString(myRideCount[index]);
846  } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
847  return toString(STEPS2TIME(myTotalRideWaitingTime[index] / MAX2(1, myRideCount[index])));
848  } else if (key == "routeLength") {
849  return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
850  } else if (key == toString(SUMO_ATTR_DURATION)) {
851  return toString(myTotalRideRouteLength[index] / MAX2(1, myRideCount[index]));
852  } else if (key == "bus") {
853  return toString(myRideBusCount[index]);
854  } else if (key == "train") {
855  return toString(myRideRailCount[index]);
856  } else if (key == "taxi") {
857  return toString(myRideTaxiCount[index]);
858  } else if (key == "bike") {
859  return toString(myRideBikeCount[index]);
860  } else if (key == "aborted") {
861  return toString(myRideAbortCount[index]);
862  }
863  throw InvalidArgument(err);
864  }
865  // vehicleTripStatistics
866  if (key == toString(SUMO_ATTR_COUNT)) {
867  return toString(myVehicleCount);
868  } else if (key == "routeLength") {
869  return toString(getAvgRouteLength());
870  } else if (key == toString(SUMO_ATTR_SPEED)) {
871  return toString(getAvgTripSpeed());
872  } else if (key == toString(SUMO_ATTR_DURATION)) {
873  return toString(getAvgDuration());
874  } else if (key == toString(SUMO_ATTR_WAITINGTIME)) {
875  return toString(getAvgWaitingTime());
876  } else if (key == toString(SUMO_ATTR_TIMELOSS)) {
877  return toString(getAvgTimeLoss());
878  } else if (key == "departDelay") {
879  return toString(getAvgDepartDelay());
880  } else if (key == "departDelayWaiting") {
882  } else if (key == "totalTravelTime") {
883  // avoid human readable output
885  } else if (key == "totalDepartDelay") {
886  return toString(getTotalDepartDelay());
887  }
888  throw InvalidArgument(err);
889 }
890 
891 
892 void
894  if (myHolder.hasDeparted()) {
896  out.writeAttr(SUMO_ATTR_ID, getID());
897  std::ostringstream internals;
898  internals << myDepartLane << " ";
899  if (!MSGlobals::gUseMesoSim) {
900  internals << myDepartPosLat << " ";
901  }
902  std::string state_arrivalLane = myArrivalLane == "" ? STATE_EMPTY_ARRIVALLANE : myArrivalLane;
903  internals << myDepartSpeed << " " << myRouteLength << " " << myWaitingTime << " " << myAmWaiting << " " << myWaitingCount << " ";
904  internals << myStoppingTime << " " << myParkingStarted << " ";
905  internals << myArrivalTime << " " << state_arrivalLane << " " << myArrivalPos << " " << myArrivalPosLat << " " << myArrivalSpeed;
906  out.writeAttr(SUMO_ATTR_STATE, internals.str());
907  out.closeTag();
908  }
909 }
910 
911 
912 void
914  std::istringstream bis(attrs.getString(SUMO_ATTR_STATE));
915  bis >> myDepartLane;
916  if (!MSGlobals::gUseMesoSim) {
917  bis >> myDepartPosLat;
918  }
923  myArrivalLane = "";
924  }
925 }
926 
927 
928 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#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:69
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define SIMSTEP
Definition: SUMOTime.h:61
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a 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:26
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:58
T MAX2(T a, T b)
Definition: StdDefs.h:82
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 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()
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
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:155
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:195
double getLength() const
return the length of the edge
Definition: MSEdge.h:670
double getVehicleMaxSpeed(const SUMOTrafficObject *const veh) const
Returns the maximum speed the vehicle may use on this edge.
Definition: MSEdge.cpp:1118
MSLane * getFirstAllowed(SUMOVehicleClass vClass, bool defaultFirst=false) const
Definition: MSEdge.cpp:674
static bool gUseMesoSim
Definition: MSGlobals.h:103
static double gLateralResolution
Definition: MSGlobals.h:97
Representation of a lane in the micro simulation.
Definition: MSLane.h:84
double getLength() const
Returns the lane's length.
Definition: MSLane.h:598
Something on a lane to be noticed about vehicle movement.
const MSLane * getLane() const
Returns the lane the reminder works on.
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.
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:184
SUMOTime getCurrentTimeStep() const
Returns the current simulation step.
Definition: MSNet.h:320
bool hasPersons() const
Returns whether persons are simulated.
Definition: MSNet.h:395
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1182
const MSEdge * getLastEdge() const
returns the destination edge
Definition: MSRoute.cpp:91
constVehIt loadedBegin() const
Returns the begin of the internal transportables map.
constVehIt loadedEnd() const
Returns the end of the internal transportables map.
virtual void erase(MSTransportable *transportable)
removes a single transportable
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:2068
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:517
const std::string & getID() const
Returns the name of the vehicle type.
Definition: MSVehicleType.h:91
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.
Definition: OptionsCont.cpp:60
Static storage of an output device and its base (abstract) implementation.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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.
Representation of a vehicle, person, or container.
virtual bool isVehicle() const
Whether it is a vehicle.
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 MSVehicleType & getVehicleType() const =0
Returns the object's "vehicle" type.
virtual SUMOVehicleClass getVClass() const =0
Returns the object's access class.
virtual const SUMOVehicleParameter & getParameter() const =0
Returns the vehicle's parameter (including departure definition)
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:62
virtual const MSRoute & getRoute() const =0
Returns the current route.
virtual SUMOTime getDeparture() const =0
Returns this vehicle's real departure time.
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 std::vector< MSVehicleDevice * > & getDevices() const =0
Returns this vehicle's devices.
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.