LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSTransportable.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.8 % 315 286
Test Date: 2024-12-21 15:45:41 Functions: 81.4 % 43 35

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-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              : /****************************************************************************/
      14              : /// @file    MSTransportable.cpp
      15              : /// @author  Melanie Weber
      16              : /// @author  Andreas Kendziorra
      17              : /// @author  Michael Behrisch
      18              : /// @date    Thu, 12 Jun 2014
      19              : ///
      20              : // The common superclass for modelling transportable objects like persons and containers
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <utils/common/StringTokenizer.h>
      25              : #include <utils/geom/GeomHelper.h>
      26              : #include <utils/vehicle/SUMOVehicleParameter.h>
      27              : #include <utils/router/PedestrianRouter.h>
      28              : #include <utils/router/IntermodalRouter.h>
      29              : #include <libsumo/TraCIConstants.h>
      30              : #include <microsim/MSEdge.h>
      31              : #include <microsim/MSLane.h>
      32              : #include <microsim/MSNet.h>
      33              : #include <microsim/MSEventControl.h>
      34              : #include <microsim/MSStoppingPlace.h>
      35              : #include <microsim/MSVehicleControl.h>
      36              : #include <microsim/devices/MSTransportableDevice.h>
      37              : #include <microsim/transportables/MSTransportableControl.h>
      38              : #include <microsim/transportables/MSPerson.h>
      39              : #include <microsim/transportables/MSStageDriving.h>
      40              : #include <microsim/transportables/MSStageTrip.h>
      41              : #include <microsim/transportables/MSStageWaiting.h>
      42              : #include <microsim/transportables/MSTransportable.h>
      43              : 
      44              : SUMOTrafficObject::NumericalID MSTransportable::myCurrentNumericalIndex = 0;
      45              : 
      46              : //#define DEBUG_PARKING
      47              : 
      48              : // ===========================================================================
      49              : // method definitions
      50              : // ===========================================================================
      51       507661 : MSTransportable::MSTransportable(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportablePlan* plan, const bool isPerson) :
      52              :     SUMOTrafficObject(pars->id),
      53       507661 :     myParameter(pars), myVType(vtype), myPlan(plan),
      54       507661 :     myAmPerson(isPerson),
      55       507661 :     myNumericalID(myCurrentNumericalIndex++) {
      56       507661 :     myStep = myPlan->begin();
      57              :     // init devices
      58       507661 :     MSDevice::buildTransportableDevices(*this, myDevices);
      59      1575764 :     for (MSStage* const stage : * myPlan) {
      60      1068103 :         stage->init(this);
      61              :     }
      62       507661 : }
      63              : 
      64              : 
      65       704385 : MSTransportable::~MSTransportable() {
      66       507610 :     if (myStep != myPlan->end() && getCurrentStageType() == MSStageType::DRIVING) {
      67        65786 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
      68        65786 :         if (stage->getVehicle() != nullptr) {
      69          125 :             stage->getVehicle()->removeTransportable(this);
      70        65661 :         } else if (stage->getOriginStop() != nullptr)  {
      71        18587 :             stage->getOriginStop()->removeTransportable(this);
      72              :         }
      73              :     }
      74       507610 :     if (myPlan != nullptr) {
      75      1794006 :         for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
      76      1286396 :             delete *i;
      77              :         }
      78       507610 :         delete myPlan;
      79       507610 :         myPlan = nullptr;
      80              :     }
      81       509872 :     for (MSTransportableDevice* dev : myDevices) {
      82         2262 :         delete dev;
      83              :     }
      84       507610 :     delete myParameter;
      85       507610 :     if (myVType->isVehicleSpecific()) {
      86           56 :         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
      87              :     }
      88       704385 : }
      89              : 
      90              : SumoRNG*
      91           56 : MSTransportable::getRNG() const {
      92           56 :     return getEdge()->getLanes()[0]->getRNG();
      93              : }
      94              : 
      95              : int
      96         2351 : MSTransportable::getRNGIndex() const {
      97         2351 :     return getEdge()->getLanes()[0]->getRNGIndex();
      98              : }
      99              : 
     100              : bool
     101      1146068 : MSTransportable::proceed(MSNet* net, SUMOTime time, const bool vehicleArrived) {
     102      1146068 :     MSStage* const prior = *myStep;
     103      1146068 :     const std::string& error = prior->setArrived(net, this, time, vehicleArrived);
     104              :     // must be done before increasing myStep to avoid invalid state for rendering
     105      1146068 :     prior->getEdge()->removeTransportable(this);
     106              :     myStep++;
     107      1146068 :     if (error != "") {
     108           78 :         throw ProcessError(error);
     109              :     }
     110              :     /* We need to check whether an access stage is needed (or maybe even two).
     111              :        The general scheme is: If the prior stage ended at a stop and the next stage
     112              :        starts at an edge which is not the one the stop is at, but the stop has an access to it
     113              :        we need an access stage. The same is true if prior ends at an edge, the next stage
     114              :        is allowed to start at any stop the edge has access to.
     115              :        If we start at a stop or end at a stop no access is needed.
     116              :     */
     117              :     bool accessToStop = false;
     118      1146029 :     if (prior->getStageType() == MSStageType::WALKING || prior->getStageType() == MSStageType::DRIVING) {
     119       258972 :         accessToStop = checkAccess(prior);
     120       887057 :     } else if (prior->getStageType() == MSStageType::WAITING_FOR_DEPART) {
     121       484580 :         for (MSTransportableDevice* const dev : myDevices) {
     122         1814 :             dev->notifyEnter(*this, MSMoveReminder::NOTIFICATION_DEPARTED, nullptr);
     123              :         }
     124              :     }
     125      1146029 :     if (!accessToStop && (myStep == myPlan->end()
     126       751032 :                           || ((*myStep)->getStageType() != MSStageType::DRIVING
     127       672404 :                               && (*myStep)->getStageType() != MSStageType::TRIP))) {
     128       204960 :         MSStoppingPlace* priorStop = prior->getStageType() == MSStageType::TRIP ? prior->getOriginStop() : prior->getDestinationStop();
     129              :         // a trip might resolve to DRIVING so we would have to stay at the stop
     130              :         // if a trip resolves to something else, this step will do stop removal
     131       858749 :         if (priorStop != nullptr) {
     132       170610 :             priorStop->removeTransportable(this);
     133              :         }
     134              :     }
     135      1146029 :     if (myStep != myPlan->end()) {
     136       753060 :         if ((*myStep)->getStageType() == MSStageType::WALKING && (prior->getStageType() != MSStageType::ACCESS || prior->getDestination() != (*myStep)->getFromEdge())) {
     137       267839 :             checkAccess(prior, false);
     138              :         }
     139       753060 :         (*myStep)->proceed(net, this, time, prior);
     140              :         return true;
     141              :     } else {
     142       392969 :         MSNet::getInstance()->getPersonControl().addArrived();
     143       392969 :         return false;
     144              :     }
     145              : }
     146              : 
     147              : 
     148              : void
     149            0 : MSTransportable::setID(const std::string& /*newID*/) {
     150            0 :     throw ProcessError(TL("Changing a transportable ID is not permitted"));
     151              : }
     152              : 
     153              : SUMOTime
     154            0 : MSTransportable::getDesiredDepart() const {
     155            0 :     return myParameter->depart;
     156              : }
     157              : 
     158              : void
     159       497363 : MSTransportable::setDeparted(SUMOTime now) {
     160       497363 :     (*myStep)->setDeparted(now);
     161       497363 : }
     162              : 
     163              : SUMOTime
     164          122 : MSTransportable::getDeparture() const {
     165          122 :     for (const MSStage* const stage : *myPlan) {
     166          122 :         if (stage->getDeparted() >= 0) {
     167          122 :             return stage->getDeparted();
     168              :         }
     169              :     }
     170              :     return -1;
     171              : }
     172              : 
     173              : 
     174              : double
     175      2156206 : MSTransportable::getEdgePos() const {
     176      2156206 :     return (*myStep)->getEdgePos(MSNet::getInstance()->getCurrentTimeStep());
     177              : }
     178              : 
     179              : double
     180         3516 : MSTransportable::getBackPositionOnLane(const MSLane* /*lane*/) const {
     181         3516 :     return getEdgePos() - getVehicleType().getLength();
     182              : }
     183              : 
     184              : int
     185       365364 : MSTransportable::getDirection() const {
     186       365364 :     return (*myStep)->getDirection();
     187              : }
     188              : 
     189              : Position
     190      5031040 : MSTransportable::getPosition() const {
     191      5031040 :     return (*myStep)->getPosition(MSNet::getInstance()->getCurrentTimeStep());
     192              : }
     193              : 
     194              : double
     195      2992292 : MSTransportable::getAngle() const {
     196      2992292 :     return (*myStep)->getAngle(MSNet::getInstance()->getCurrentTimeStep());
     197              : }
     198              : 
     199              : double
     200          604 : MSTransportable::getWaitingSeconds() const {
     201          604 :     return STEPS2TIME((*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep()));
     202              : }
     203              : 
     204              : double
     205       838945 : MSTransportable::getSpeed() const {
     206       838945 :     return (*myStep)->getSpeed();
     207              : }
     208              : 
     209              : 
     210              : void
     211        55538 : MSTransportable::tripInfoOutput(OutputDevice& os) const {
     212        55538 :     SUMOTime departure = myPlan->front()->getDeparted();
     213       111928 :     os.openTag(isPerson() ? "personinfo" : "containerinfo");
     214              :     os.writeAttr(SUMO_ATTR_ID, getID());
     215        55538 :     os.writeAttr(SUMO_ATTR_DEPART, departure >= 0 ? time2string(departure) : "-1");
     216        55538 :     os.writeAttr(SUMO_ATTR_TYPE, getVehicleType().getID());
     217        55538 :     if (isPerson()) {
     218       109372 :         os.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
     219              :     }
     220              :     SUMOTime duration = 0;
     221              :     SUMOTime waitingTime = 0;
     222              :     SUMOTime timeLoss = 0;
     223              :     SUMOTime travelTime = 0;
     224              :     bool durationOK = true;
     225              :     bool waitingTimeOK = true;
     226              :     bool timeLossOK = true;
     227              :     bool travelTimeOK = true;
     228       186195 :     for (MSStage* const i : *myPlan) {
     229       130657 :         SUMOTime t = i->getDuration();
     230       130657 :         if (t != SUMOTime_MAX) {
     231       130376 :             duration += t;
     232              :         } else {
     233              :             durationOK = false;
     234              :         }
     235       130657 :         t = i->getWaitingTime();
     236       130657 :         if (t != SUMOTime_MAX) {
     237       130652 :             waitingTime += t;
     238              :         } else {
     239              :             waitingTimeOK = false;
     240              :         }
     241       130657 :         t = i->getTimeLoss(this);
     242       130657 :         if (t != SUMOTime_MAX) {
     243       130390 :             timeLoss += t;
     244              :         } else {
     245              :             timeLossOK = false;
     246              :         }
     247       130657 :         t = i->getTravelTime();
     248       130657 :         if (t != SUMOTime_MAX) {
     249       130378 :             travelTime += t;
     250              :         } else {
     251              :             travelTimeOK = false;
     252              :         }
     253              :     }
     254        55538 :     os.writeAttr(SUMO_ATTR_DURATION, durationOK ? time2string(duration) : "-1");
     255        55538 :     os.writeAttr(SUMO_ATTR_WAITINGTIME, waitingTimeOK ? time2string(waitingTime) : "-1");
     256        55538 :     os.writeAttr(SUMO_ATTR_TIMELOSS, timeLossOK ? time2string(timeLoss) : "-1");
     257        55538 :     os.writeAttr(SUMO_ATTR_TRAVELTIME, travelTimeOK ? time2string(travelTime) : "-1");
     258       186195 :     for (MSStage* const i : *myPlan) {
     259       130657 :         i->tripInfoOutput(os, this);
     260              :     }
     261        55538 :     os.closeTag();
     262        55538 : }
     263              : 
     264              : 
     265              : void
     266         2691 : MSTransportable::routeOutput(OutputDevice& os, const bool withRouteLength) const {
     267              :     const std::string typeID = (
     268         5314 :                                    (isPerson() && getVehicleType().getID() == DEFAULT_PEDTYPE_ID)
     269         5314 :                                    || (isContainer() && getVehicleType().getID() == DEFAULT_CONTAINERTYPE_ID)) ? "" : getVehicleType().getID();
     270         2759 :     myParameter->write(os, OptionsCont::getOptions(), isPerson() ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, typeID);
     271         2691 :     if (hasArrived()) {
     272         5262 :         os.writeAttr("arrival", time2string(MSNet::getInstance()->getCurrentTimeStep()));
     273              :     }
     274              :     const MSStage* previous = nullptr;
     275        10809 :     for (const MSStage* const stage : *myPlan) {
     276         8118 :         stage->routeOutput(myAmPerson, os, withRouteLength, previous);
     277              :         previous = stage;
     278              :     }
     279         2691 :     myParameter->writeParams(os);
     280         2691 :     os.closeTag();
     281         2691 :     os.lf();
     282         2691 : }
     283              : 
     284              : 
     285              : void
     286           32 : MSTransportable::setAbortWaiting(const SUMOTime timeout) {
     287           32 :     if (timeout < 0 && myAbortCommand != nullptr) {
     288              :         myAbortCommand->deschedule();
     289           16 :         myAbortCommand = nullptr;
     290           16 :         return;
     291              :     }
     292           16 :     myAbortCommand = new WrappingCommand<MSTransportable>(this, &MSTransportable::abortStage);
     293           16 :     MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myAbortCommand, SIMSTEP + timeout);
     294              : }
     295              : 
     296              : 
     297              : SUMOTime
     298           16 : MSTransportable::abortStage(SUMOTime step) {
     299           48 :     WRITE_WARNINGF(TL("Teleporting % '%'; waited too long, from edge '%', time=%."),
     300              :                    isPerson() ? "person" : "container", getID(), (*myStep)->getEdge()->getID(), time2string(step));
     301           16 :     MSTransportableControl& tc = isPerson() ? MSNet::getInstance()->getPersonControl() : MSNet::getInstance()->getContainerControl();
     302              :     tc.registerTeleportAbortWait();
     303           16 :     (*myStep)->abort(this);
     304           16 :     if (!proceed(MSNet::getInstance(), step)) {
     305            8 :         tc.erase(this);
     306              :     }
     307           16 :     return 0;
     308              : }
     309              : 
     310              : 
     311              : void
     312       214342 : MSTransportable::appendStage(MSStage* stage, int next) {
     313              :     // myStep is invalidated upon modifying myPlan
     314       214342 :     const int stepIndex = (int)(myStep - myPlan->begin());
     315       214342 :     if (next < 0) {
     316          388 :         myPlan->push_back(stage);
     317              :     } else {
     318       213954 :         if (stepIndex + next > (int)myPlan->size()) {
     319            0 :             throw ProcessError("invalid index '" + toString(next) + "' for inserting new stage into plan of '" + getID() + "'");
     320              :         }
     321       213954 :         myPlan->insert(myPlan->begin() + stepIndex + next, stage);
     322              :     }
     323       214342 :     myStep = myPlan->begin() + stepIndex;
     324       214342 : }
     325              : 
     326              : 
     327              : void
     328         1771 : MSTransportable::removeStage(int next, bool stayInSim) {
     329              :     assert(myStep + next < myPlan->end());
     330              :     assert(next >= 0);
     331         1771 :     if (next > 0) {
     332              :         // myStep is invalidated upon modifying myPlan
     333           81 :         int stepIndex = (int)(myStep - myPlan->begin());
     334           81 :         delete *(myStep + next);
     335           81 :         myPlan->erase(myStep + next);
     336           81 :         myStep = myPlan->begin() + stepIndex;
     337              :     } else {
     338         1690 :         if (myStep + 1 == myPlan->end() && stayInSim) {
     339              :             // stay in the simulation until the start of simStep to allow appending new stages (at the correct position)
     340          166 :             appendStage(new MSStageWaiting(getEdge(), nullptr, 0, 0, getEdgePos(), "last stage removed", false));
     341              :         }
     342         1690 :         (*myStep)->abort(this);
     343         1690 :         if (!proceed(MSNet::getInstance(), SIMSTEP)) {
     344           52 :             MSNet::getInstance()->getPersonControl().erase(this);
     345         1638 :         } else if (myPlan->front()->getDeparted() < 0) {
     346           43 :             myPlan->front()->setDeparted(SIMSTEP);
     347              :         }
     348              :     }
     349         1771 : }
     350              : 
     351              : 
     352              : void
     353           16 : MSTransportable::setSpeed(double speed) {
     354           42 :     for (MSTransportablePlan::const_iterator i = myStep; i != myPlan->end(); ++i) {
     355           26 :         (*i)->setSpeed(speed);
     356              :     }
     357           16 :     getSingularType().setMaxSpeed(speed);
     358           16 : }
     359              : 
     360              : 
     361              : bool
     362            0 : MSTransportable::replaceRoute(ConstMSRoutePtr newRoute, const std::string& /* info */, bool /* onInit */, int /* offset */, bool /* addRouteStops */, bool /* removeStops */, std::string* /* msgReturn */) {
     363            0 :     if (isPerson()) {
     364            0 :         static_cast<MSPerson*>(this)->replaceWalk(newRoute->getEdges(), getPositionOnLane(), 0, 1);
     365            0 :         return true;
     366              :     }
     367              :     return false;
     368              : }
     369              : 
     370              : 
     371              : bool
     372          100 : MSTransportable::reroute(SUMOTime t, const std::string& /* info */, MSTransportableRouter& router, const bool /* onInit */, const bool /* withTaz */, const bool /* silent */, const MSEdge* /* sink */) {
     373              :     MSStageTrip* trip = getCurrentStage()->getTrip();
     374          100 :     if (trip == nullptr) {
     375              :         // TODO this should be possible after factoring out MSStageTrip::reroute
     376              :         return false;
     377              :     }
     378          100 :     if (getCurrentStage()->getVehicle() != nullptr) {
     379              :         // TODO rerouting during a ride still needs to be implemented
     380              :         return false;
     381              :     }
     382              :     // find the final stage of the trip
     383              :     int tripEndOffset = -1;
     384           80 :     for (int i = getNumRemainingStages() - 1; i >= 0; i--) {
     385           80 :         if (getNextStage(i)->getTrip() == trip) {
     386              :             tripEndOffset = i;
     387              :             break;
     388              :         }
     389              :     }
     390              :     std::vector<MSStage*> stages;
     391           80 :     MSStageWaiting start(getEdge(), getCurrentStage()->getOriginStop(), -1, t, getEdgePos(), "start", true);
     392           80 :     if (trip->reroute(t, router, this, &start, getEdge(), getRerouteDestination(), stages) == "") {
     393              :         // check whether the new plan actually differs
     394          150 :         while (tripEndOffset >= 0 && !stages.empty() && stages.back()->equals(*getNextStage(tripEndOffset))) {
     395           70 :             delete stages.back();
     396              :             stages.pop_back();
     397           70 :             tripEndOffset--;
     398              :         }
     399              :         bool abortCurrent = true;
     400              :         // check whether the future route of the current stage is identical to the route
     401           80 :         if (!stages.empty() && stages.front()->isWalk() && getCurrentStage()->isWalk()) {
     402              :             // TODO this check should be done for rides as well
     403              :             MSStageMoving* s = static_cast<MSStageMoving*>(getCurrentStage());
     404           48 :             int routeIndex = (int)(s->getRouteStep() - s->getRoute().begin());
     405           48 :             ConstMSEdgeVector oldEdges = s->getEdges();
     406              :             oldEdges.erase(oldEdges.begin(), oldEdges.begin() + routeIndex);
     407           48 :             ConstMSEdgeVector newEdges = stages.front()->getEdges();
     408           48 :             if (newEdges == oldEdges) {
     409           48 :                 delete stages.front();
     410              :                 stages.erase(stages.begin());
     411              :                 abortCurrent = false;
     412              :             }
     413           48 :         }
     414           80 :         if (stages.empty()) {
     415              :             return false;
     416              :         }
     417              :         // remove future stages of the trip
     418           12 :         for (int i = tripEndOffset; i >= 1; i--) {
     419            6 :             removeStage(i);
     420              :         }
     421              :         // insert new stages of the rerouting
     422              :         int idx = 1;
     423           12 :         for (MSStage* stage : stages) {
     424            6 :             appendStage(stage, idx++);
     425              :         }
     426            6 :         if (abortCurrent) {
     427            0 :             removeStage(0);
     428              :         }
     429            6 :         return true;
     430              :     }
     431              :     return false;
     432           80 : }
     433              : 
     434              : 
     435              : void
     436           73 : MSTransportable::replaceVehicleType(MSVehicleType* type) {
     437           73 :     const SUMOVehicleClass oldVClass = myVType->getVehicleClass();
     438           73 :     if (myVType->isVehicleSpecific()) {
     439            1 :         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
     440              :     }
     441           73 :     if (isPerson()
     442           73 :             && type->getVehicleClass() != oldVClass
     443           10 :             && type->getVehicleClass() != SVC_PEDESTRIAN
     444           78 :             && !type->getParameter().wasSet(VTYPEPARS_VEHICLECLASS_SET)) {
     445           15 :         WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), getID(), type->getID(), toString(type->getVehicleClass()));
     446              :     }
     447           73 :     myVType = type;
     448           73 : }
     449              : 
     450              : 
     451              : MSVehicleType&
     452           80 : MSTransportable::getSingularType() {
     453           80 :     if (myVType->isVehicleSpecific()) {
     454              :         return *myVType;
     455              :     }
     456          114 :     MSVehicleType* type = myVType->buildSingularType(myVType->getID() + "@" + getID());
     457           57 :     replaceVehicleType(type);
     458           57 :     return *type;
     459              : }
     460              : 
     461              : 
     462              : PositionVector
     463      1095668 : MSTransportable::getBoundingBox() const {
     464      1095668 :     PositionVector centerLine;
     465      1095668 :     const Position p = getPosition();
     466      1095668 :     const double angle = getAngle();
     467      1095668 :     const double length = getVehicleType().getLength();
     468      1095668 :     const Position back = p + Position(-cos(angle) * length, -sin(angle) * length);
     469      1095668 :     centerLine.push_back(p);
     470      1095668 :     centerLine.push_back(back);
     471      1095668 :     centerLine.move2side(0.5 * getVehicleType().getWidth());
     472              :     PositionVector result = centerLine;
     473      1095668 :     centerLine.move2side(-getVehicleType().getWidth());
     474      1095668 :     result.append(centerLine.reverse(), POSITION_EPS);
     475              :     //std::cout << " transp=" << getID() << " p=" << p << " angle=" << GeomHelper::naviDegree(angle) << " back=" << back << " result=" << result << "\n";
     476      1095668 :     return result;
     477      1095668 : }
     478              : 
     479              : 
     480              : std::string
     481            0 : MSTransportable::getStageSummary(int stageIndex) const {
     482              :     assert(stageIndex < (int)myPlan->size());
     483              :     assert(stageIndex >= 0);
     484            0 :     return (*myPlan)[stageIndex]->getStageSummary(myAmPerson);
     485              : }
     486              : 
     487              : 
     488              : const std::set<SUMOTrafficObject::NumericalID>
     489            0 : MSTransportable::getUpcomingEdgeIDs() const {
     490              :     std::set<SUMOTrafficObject::NumericalID> result;
     491            0 :     for (auto step = myStep; step != myPlan->end(); ++step) {
     492            0 :         for (const MSEdge* const e : (*step)->getEdges()) {
     493            0 :             result.insert(e->getNumericalID());
     494            0 :         }
     495              :     }
     496            0 :     return result;
     497              : }
     498              : 
     499              : 
     500              : bool
     501      3952497 : MSTransportable::hasArrived() const {
     502      3952497 :     return myStep == myPlan->end();
     503              : }
     504              : 
     505              : bool
     506        18619 : MSTransportable::hasDeparted() const {
     507        18619 :     return myPlan->size() > 0 && (myPlan->front()->getDeparted() >= 0 || myStep > myPlan->begin());
     508              : }
     509              : 
     510              : 
     511              : void
     512           45 : MSTransportable::rerouteParkingArea(MSStoppingPlace* orig, MSStoppingPlace* replacement) {
     513              :     // check whether the transportable was riding to the orignal stop
     514              :     // @note: parkingArea can currently not be set as myDestinationStop so we
     515              :     // check for stops on the edge instead
     516              : #ifdef DEBUG_PARKING
     517              :     std::cout << SIMTIME << " person=" << getID() << " rerouteParkingArea orig=" << orig->getID() << " replacement=" << replacement->getID() << "\n";
     518              : #endif
     519              :     assert(getCurrentStageType() == MSStageType::DRIVING);
     520           45 :     if (!myAmPerson) {
     521            0 :         WRITE_WARNING(TL("parkingAreaReroute not supported for containers"));
     522            0 :         return;
     523              :     }
     524           45 :     if (getDestination() == &orig->getLane().getEdge()) {
     525           45 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
     526              :         assert(stage != 0);
     527              :         assert(stage->getVehicle() != 0);
     528              :         // adapt plan
     529           45 :         stage->setDestination(&replacement->getLane().getEdge(), replacement);
     530           45 :         stage->setArrivalPos((replacement->getBeginLanePosition() + replacement->getEndLanePosition()) / 2);
     531              : #ifdef DEBUG_PARKING
     532              :         std::cout << " set ride destination\n";
     533              : #endif
     534           45 :         if (myStep + 1 == myPlan->end()) {
     535              :             return;
     536              :         }
     537              :         // if the next step is a walk, adapt the route
     538           45 :         MSStage* nextStage = *(myStep + 1);
     539           45 :         if (nextStage->getStageType() == MSStageType::TRIP) {
     540           35 :             dynamic_cast<MSStageTrip*>(nextStage)->setOrigin(stage->getDestination());
     541              : #ifdef DEBUG_PARKING
     542              :             std::cout << " set subsequent trip origin\n";
     543              : #endif
     544           10 :         } else if (nextStage->getStageType() == MSStageType::WALKING) {
     545              : #ifdef DEBUG_PARKING
     546              :             std::cout << " replace subsequent walk with a trip\n";
     547              : #endif
     548              :             MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
     549            5 :                                                     nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
     550            5 :             removeStage(1);
     551            5 :             appendStage(newStage, 1);
     552            5 :         } else if (nextStage->getStageType() == MSStageType::WAITING) {
     553              : #ifdef DEBUG_PARKING
     554              :             std::cout << " add subsequent walk to reach stop\n";
     555              :             std::cout << "   arrivalPos=" << nextStage->getArrivalPos() << "\n";
     556              : #endif
     557              :             MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
     558            5 :                                                     nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
     559            5 :             appendStage(newStage, 1);
     560              :         }
     561              :         // if the plan contains another ride with the same vehicle from the same
     562              :         // parking area, adapt the preceeding walk to end at the replacement
     563           90 :         for (auto it = myStep + 2; it != myPlan->end(); it++) {
     564           55 :             MSStage* const futureStage = *it;
     565           55 :             MSStage* const prevStage = *(it - 1);
     566           55 :             if (futureStage->getStageType() == MSStageType::DRIVING) {
     567              :                 MSStageDriving* const ds = static_cast<MSStageDriving*>(futureStage);
     568              :                 // ride origin is set implicitly from the walk destination
     569              :                 ds->setOrigin(nullptr);
     570              :                 if (ds->getLines() == stage->getLines()
     571           10 :                         && prevStage->getDestination() == &orig->getLane().getEdge()) {
     572           10 :                     if (prevStage->getStageType() == MSStageType::TRIP) {
     573            5 :                         dynamic_cast<MSStageTrip*>(prevStage)->setDestination(stage->getDestination(), replacement);
     574              : #ifdef DEBUG_PARKING
     575              :                         std::cout << " replace later trip before ride (" << (it - myPlan->begin()) << ")\n";
     576              : #endif
     577            5 :                     } else if (prevStage->getStageType() == MSStageType::WALKING) {
     578              : #ifdef DEBUG_PARKING
     579              :                         std::cout << " replace later walk before ride (" << (it - myPlan->begin()) << ")\n";
     580              : #endif
     581            5 :                         MSStageTrip* newStage = new MSStageTrip(prevStage->getFromEdge(), nullptr, stage->getDestination(),
     582           10 :                                                                 replacement, -1, 0, "", -1, 1, getID(), 0, true, stage->getArrivalPos());
     583            5 :                         int prevStageRelIndex = (int)(it - 1 - myStep);
     584            5 :                         removeStage(prevStageRelIndex);
     585            5 :                         appendStage(newStage, prevStageRelIndex);
     586              :                     }
     587              :                     break;
     588              :                 }
     589              :             }
     590              :         }
     591              :     }
     592              : }
     593              : 
     594              : 
     595              : MSDevice*
     596       646300 : MSTransportable::getDevice(const std::type_info& type) const {
     597       851096 :     for (MSTransportableDevice* const dev : myDevices) {
     598       727493 :         if (typeid(*dev) == type) {
     599              :             return dev;
     600              :         }
     601              :     }
     602              :     return nullptr;
     603              : }
     604              : 
     605              : 
     606              : void
     607           10 : MSTransportable::setJunctionModelParameter(const std::string& key, const std::string& value) {
     608           15 :     if (key == toString(SUMO_ATTR_JM_IGNORE_IDS) || key == toString(SUMO_ATTR_JM_IGNORE_TYPES)) {
     609            5 :         getParameter().parametersSet |= VEHPARS_JUNCTIONMODEL_PARAMS_SET;
     610            5 :         const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
     611              :         // checked in MSLink::ignoreFoe
     612              :     } else {
     613           10 :         throw InvalidArgument(getObjectType() + " '" + getID() + "' does not support junctionModel parameter '" + key + "'");
     614              :     }
     615            5 : }
     616              : 
     617              : 
     618              : double
     619            0 : MSTransportable::getSlope() const {
     620            0 :     const MSEdge* edge = getEdge();
     621            0 :     const double ep = getEdgePos();
     622            0 :     const double gp = edge->getLanes()[0]->interpolateLanePosToGeometryPos(ep);
     623            0 :     return edge->getLanes()[0]->getShape().slopeDegreeAtOffset(gp);
     624              : }
     625              : 
     626              : 
     627              : SUMOTime
     628            0 : MSTransportable::getWaitingTime(const bool /* accumulated */) const {
     629            0 :     return (*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep());
     630              : }
     631              : 
     632              : 
     633              : double
     634    140022269 : MSTransportable::getMaxSpeed() const {
     635    140022269 :     return MIN2(getVehicleType().getMaxSpeed(), getVehicleType().getDesiredMaxSpeed() * getChosenSpeedFactor());
     636              : }
     637              : 
     638              : 
     639              : SUMOVehicleClass
     640      2653384 : MSTransportable::getVClass() const {
     641      2653384 :     return getVehicleType().getVehicleClass();
     642              : }
     643              : 
     644              : 
     645              : int
     646            0 : MSTransportable::getRoutingMode() const {
     647              :     /// @todo: allow configuring routing mode
     648            0 :     return libsumo::ROUTING_MODE_DEFAULT;
     649              : }
     650              : 
     651              : void
     652           43 : MSTransportable::saveState(OutputDevice& out) {
     653              :     // this saves lots of departParameters which are only needed for transportables that did not yet depart
     654              :     // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
     655           43 :     const SUMOTime desiredDepart = myParameter->depart;
     656           43 :     if (myPlan->front()->getDeparted() >= 0) {
     657              :         // this is only relevant in the context of delayed departure (max-num-persons)
     658           37 :         const_cast<SUMOVehicleParameter*>(myParameter)->depart = myPlan->front()->getDeparted();
     659              :     }
     660           43 :     myParameter->write(out, OptionsCont::getOptions(), myAmPerson ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, getVehicleType().getID());
     661           43 :     const_cast<SUMOVehicleParameter*>(myParameter)->depart = desiredDepart;
     662           43 :     if (!myParameter->wasSet(VEHPARS_SPEEDFACTOR_SET) && getChosenSpeedFactor() != 1) {
     663           41 :         out.setPrecision(MAX2(gPrecisionRandom, gPrecision));
     664           41 :         out.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
     665           41 :         out.setPrecision(gPrecision);
     666              :     }
     667           43 :     int stepIdx = (int)(myStep - myPlan->begin());
     668          101 :     for (auto it = myPlan->begin(); it != myStep; ++it) {
     669           58 :         const MSStageType st = (*it)->getStageType();
     670           58 :         if (st == MSStageType::TRIP || st == MSStageType::ACCESS) {
     671           19 :             stepIdx--;
     672              :         }
     673              :     }
     674           43 :     std::ostringstream state;
     675           86 :     state << myParameter->parametersSet << " " << stepIdx;
     676           43 :     (*myStep)->saveState(state);
     677           43 :     out.writeAttr(SUMO_ATTR_STATE, state.str());
     678              :     const MSStage* previous = nullptr;
     679          150 :     for (const MSStage* const stage : *myPlan) {
     680          107 :         stage->routeOutput(myAmPerson, out, false, previous);
     681              :         previous = stage;
     682              :     }
     683           43 :     out.closeTag();
     684           43 : }
     685              : 
     686              : 
     687              : void
     688           48 : MSTransportable::loadState(const std::string& state) {
     689           48 :     std::istringstream iss(state);
     690              :     int step;
     691           48 :     iss >> myParameter->parametersSet >> step;
     692           48 :     myPlan->front()->setDeparted(myParameter->depart);
     693           48 :     myStep = myPlan->begin() + step;
     694           48 :     (*myStep)->loadState(this, iss);
     695           48 : }
     696              : 
     697              : 
     698              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1