LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSTransportable.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 257 282 91.1 %
Date: 2024-05-07 15:28:01 Functions: 35 42 83.3 %

          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      457026 : MSTransportable::MSTransportable(const SUMOVehicleParameter* pars, MSVehicleType* vtype, MSTransportablePlan* plan, const bool isPerson) :
      52             :     SUMOTrafficObject(pars->id),
      53      457026 :     myParameter(pars), myVType(vtype), myPlan(plan),
      54      457026 :     myAmPerson(isPerson),
      55      457026 :     myNumericalID(myCurrentNumericalIndex++) {
      56      457026 :     myStep = myPlan->begin();
      57             :     // init devices
      58      457026 :     MSDevice::buildTransportableDevices(*this, myDevices);
      59     1378053 :     for (MSStage* const stage : * myPlan) {
      60      921027 :         stage->init(this);
      61             :     }
      62      457026 : }
      63             : 
      64             : 
      65      595328 : MSTransportable::~MSTransportable() {
      66      456976 :     if (myStep != myPlan->end() && getCurrentStageType() == MSStageType::DRIVING) {
      67       29749 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
      68       29749 :         if (stage->getVehicle() != nullptr) {
      69         135 :             stage->getVehicle()->removeTransportable(this);
      70       29614 :         } else if (stage->getOriginStop() != nullptr)  {
      71         439 :             stage->getOriginStop()->removeTransportable(this);
      72             :         }
      73             :     }
      74      456976 :     if (myPlan != nullptr) {
      75     1626898 :         for (MSTransportablePlan::const_iterator i = myPlan->begin(); i != myPlan->end(); ++i) {
      76     1169922 :             delete *i;
      77             :         }
      78      456976 :         delete myPlan;
      79      456976 :         myPlan = nullptr;
      80             :     }
      81      710371 :     for (MSTransportableDevice* dev : myDevices) {
      82      253395 :         delete dev;
      83             :     }
      84      456976 :     delete myParameter;
      85      456976 :     if (myVType->isVehicleSpecific()) {
      86          58 :         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
      87             :     }
      88      595328 : }
      89             : 
      90             : SumoRNG*
      91          67 : MSTransportable::getRNG() const {
      92          67 :     return getEdge()->getLanes()[0]->getRNG();
      93             : }
      94             : 
      95             : int
      96        2240 : MSTransportable::getRNGIndex() const {
      97        2240 :     return getEdge()->getLanes()[0]->getRNGIndex();
      98             : }
      99             : 
     100             : bool
     101     1103748 : MSTransportable::proceed(MSNet* net, SUMOTime time, const bool vehicleArrived) {
     102     1103748 :     MSStage* const prior = *myStep;
     103     1103748 :     const std::string& error = prior->setArrived(net, this, time, vehicleArrived);
     104             :     // must be done before increasing myStep to avoid invalid state for rendering
     105     1103748 :     prior->getEdge()->removeTransportable(this);
     106             :     myStep++;
     107     1103748 :     if (error != "") {
     108          64 :         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     1103716 :     if (prior->getStageType() == MSStageType::WALKING || prior->getStageType() == MSStageType::DRIVING) {
     119      304818 :         accessToStop = checkAccess(prior);
     120      798898 :     } else if (prior->getStageType() == MSStageType::WAITING_FOR_DEPART) {
     121      676539 :         for (MSTransportableDevice* const dev : myDevices) {
     122      236308 :             dev->notifyEnter(*this, MSMoveReminder::NOTIFICATION_DEPARTED, nullptr);
     123             :         }
     124             :     }
     125     1103716 :     if (!accessToStop && (myStep == myPlan->end()
     126      692945 :                           || ((*myStep)->getStageType() != MSStageType::DRIVING
     127      649069 :                               && (*myStep)->getStageType() != MSStageType::TRIP))) {
     128      822300 :         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      822300 :         if (priorStop != nullptr) {
     132       72272 :             priorStop->removeTransportable(this);
     133             :         }
     134             :     }
     135     1103716 :     if (myStep != myPlan->end()) {
     136      695519 :         if ((*myStep)->getStageType() == MSStageType::WALKING && (prior->getStageType() != MSStageType::ACCESS || prior->getDestination() != (*myStep)->getFromEdge())) {
     137      292632 :             checkAccess(prior, false);
     138             :         }
     139      695519 :         (*myStep)->proceed(net, this, time, prior);
     140             :         return true;
     141             :     } else {
     142      408197 :         MSNet::getInstance()->getPersonControl().addArrived();
     143      408197 :         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       47732 : MSTransportable::getDesiredDepart() const {
     155       47732 :     return myParameter->depart;
     156             : }
     157             : 
     158             : void
     159       17806 : MSTransportable::setDeparted(SUMOTime now) {
     160       17806 :     (*myStep)->setDeparted(now);
     161       17806 : }
     162             : 
     163             : SUMOTime
     164         122 : MSTransportable::getDeparture() const {
     165         262 :     for (const MSStage* const stage : *myPlan) {
     166         262 :         if (stage->getDeparted() >= 0) {
     167         122 :             return stage->getDeparted();
     168             :         }
     169             :     }
     170             :     return -1;
     171             : }
     172             : 
     173             : 
     174             : double
     175     2113784 : MSTransportable::getEdgePos() const {
     176     2113784 :     return (*myStep)->getEdgePos(MSNet::getInstance()->getCurrentTimeStep());
     177             : }
     178             : 
     179             : double
     180        3477 : MSTransportable::getBackPositionOnLane(const MSLane* /*lane*/) const {
     181        3477 :     return getEdgePos() - getVehicleType().getLength();
     182             : }
     183             : 
     184             : int
     185      359982 : MSTransportable::getDirection() const {
     186      359982 :     return (*myStep)->getDirection();
     187             : }
     188             : 
     189             : Position
     190     5094400 : MSTransportable::getPosition() const {
     191     5094400 :     return (*myStep)->getPosition(MSNet::getInstance()->getCurrentTimeStep());
     192             : }
     193             : 
     194             : double
     195     2934775 : MSTransportable::getAngle() const {
     196     2934775 :     return (*myStep)->getAngle(MSNet::getInstance()->getCurrentTimeStep());
     197             : }
     198             : 
     199             : double
     200        1198 : MSTransportable::getWaitingSeconds() const {
     201        1198 :     return STEPS2TIME((*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep()));
     202             : }
     203             : 
     204             : double
     205      836061 : MSTransportable::getSpeed() const {
     206      836061 :     return (*myStep)->getSpeed();
     207             : }
     208             : 
     209             : 
     210             : void
     211       47732 : MSTransportable::tripInfoOutput(OutputDevice& os) const {
     212       96176 :     os.openTag(isPerson() ? "personinfo" : "containerinfo");
     213             :     os.writeAttr(SUMO_ATTR_ID, getID());
     214       47732 :     os.writeAttr(SUMO_ATTR_DEPART, time2string(getDesiredDepart()));
     215       47732 :     os.writeAttr(SUMO_ATTR_TYPE, getVehicleType().getID());
     216       47732 :     if (isPerson()) {
     217       94040 :         os.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
     218             :     }
     219             :     SUMOTime duration = 0;
     220             :     SUMOTime waitingTime = 0;
     221             :     SUMOTime timeLoss = 0;
     222             :     SUMOTime travelTime = 0;
     223             :     bool durationOK = true;
     224             :     bool waitingTimeOK = true;
     225             :     bool timeLossOK = true;
     226             :     bool travelTimeOK = true;
     227      166093 :     for (MSStage* const i : *myPlan) {
     228      118361 :         SUMOTime t = i->getDuration();
     229      118361 :         if (t != SUMOTime_MAX) {
     230      118099 :             duration += t;
     231             :         } else {
     232             :             durationOK = false;
     233             :         }
     234      118361 :         t = i->getWaitingTime();
     235      118361 :         if (t != SUMOTime_MAX) {
     236      118355 :             waitingTime += t;
     237             :         } else {
     238             :             waitingTimeOK = false;
     239             :         }
     240      118361 :         t = i->getTimeLoss(this);
     241      118361 :         if (t != SUMOTime_MAX) {
     242      118121 :             timeLoss += t;
     243             :         } else {
     244             :             timeLossOK = false;
     245             :         }
     246      118361 :         t = i->getTravelTime();
     247      118361 :         if (t != SUMOTime_MAX) {
     248      118101 :             travelTime += t;
     249             :         } else {
     250             :             travelTimeOK = false;
     251             :         }
     252             :     }
     253       47732 :     os.writeAttr(SUMO_ATTR_DURATION, durationOK ? time2string(duration) : "-1");
     254       47732 :     os.writeAttr(SUMO_ATTR_WAITINGTIME, waitingTimeOK ? time2string(waitingTime) : "-1");
     255       47732 :     os.writeAttr(SUMO_ATTR_TIMELOSS, timeLossOK ? time2string(timeLoss) : "-1");
     256       47732 :     os.writeAttr(SUMO_ATTR_TRAVELTIME, travelTimeOK ? time2string(travelTime) : "-1");
     257      166093 :     for (MSStage* const i : *myPlan) {
     258      118361 :         i->tripInfoOutput(os, this);
     259             :     }
     260       47732 :     os.closeTag();
     261       47732 : }
     262             : 
     263             : 
     264             : void
     265        2678 : MSTransportable::routeOutput(OutputDevice& os, const bool withRouteLength) const {
     266             :     const std::string typeID = (
     267        5296 :                                    (isPerson() && getVehicleType().getID() == DEFAULT_PEDTYPE_ID)
     268        5296 :                                    || (isContainer() && getVehicleType().getID() == DEFAULT_CONTAINERTYPE_ID)) ? "" : getVehicleType().getID();
     269        2738 :     myParameter->write(os, OptionsCont::getOptions(), isPerson() ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, typeID);
     270        2678 :     if (hasArrived()) {
     271        5232 :         os.writeAttr("arrival", time2string(MSNet::getInstance()->getCurrentTimeStep()));
     272             :     }
     273             :     const MSStage* previous = nullptr;
     274       10581 :     for (const MSStage* const stage : *myPlan) {
     275        7903 :         stage->routeOutput(myAmPerson, os, withRouteLength, previous);
     276             :         previous = stage;
     277             :     }
     278        2678 :     myParameter->writeParams(os);
     279        2678 :     os.closeTag();
     280        2678 :     os.lf();
     281        2678 : }
     282             : 
     283             : 
     284             : void
     285          32 : MSTransportable::setAbortWaiting(const SUMOTime timeout) {
     286          32 :     if (timeout < 0 && myAbortCommand != nullptr) {
     287             :         myAbortCommand->deschedule();
     288          16 :         myAbortCommand = nullptr;
     289          16 :         return;
     290             :     }
     291          16 :     myAbortCommand = new WrappingCommand<MSTransportable>(this, &MSTransportable::abortStage);
     292          16 :     MSNet::getInstance()->getBeginOfTimestepEvents()->addEvent(myAbortCommand, SIMSTEP + timeout);
     293             : }
     294             : 
     295             : 
     296             : SUMOTime
     297          16 : MSTransportable::abortStage(SUMOTime step) {
     298          48 :     WRITE_WARNINGF(TL("Teleporting % '%'; waited too long, from edge '%', time=%."),
     299             :                    isPerson() ? "person" : "container", getID(), (*myStep)->getEdge()->getID(), time2string(step));
     300          16 :     MSTransportableControl& tc = isPerson() ? MSNet::getInstance()->getPersonControl() : MSNet::getInstance()->getContainerControl();
     301             :     tc.registerTeleportAbortWait();
     302          16 :     (*myStep)->abort(this);
     303          16 :     if (!proceed(MSNet::getInstance(), step)) {
     304           8 :         tc.erase(this);
     305             :     }
     306          16 :     return 0;
     307             : }
     308             : 
     309             : 
     310             : 
     311             : void
     312      244031 : MSTransportable::appendStage(MSStage* stage, int next) {
     313             :     // myStep is invalidated upon modifying myPlan
     314      244031 :     const int stepIndex = (int)(myStep - myPlan->begin());
     315      244031 :     if (next < 0) {
     316         479 :         myPlan->push_back(stage);
     317             :     } else {
     318      243552 :         if (stepIndex + next > (int)myPlan->size()) {
     319           0 :             throw ProcessError("invalid index '" + toString(next) + "' for inserting new stage into plan of '" + getID() + "'");
     320             :         }
     321      243552 :         myPlan->insert(myPlan->begin() + stepIndex + next, stage);
     322             :     }
     323      244031 :     myStep = myPlan->begin() + stepIndex;
     324      244031 : }
     325             : 
     326             : 
     327             : void
     328        1828 : MSTransportable::removeStage(int next, bool stayInSim) {
     329             :     assert(myStep + next < myPlan->end());
     330             :     assert(next >= 0);
     331        1828 :     if (next > 0) {
     332             :         // myStep is invalidated upon modifying myPlan
     333          60 :         int stepIndex = (int)(myStep - myPlan->begin());
     334          60 :         delete *(myStep + next);
     335          60 :         myPlan->erase(myStep + next);
     336          60 :         myStep = myPlan->begin() + stepIndex;
     337             :     } else {
     338        1768 :         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         288 :             appendStage(new MSStageWaiting(getEdge(), nullptr, 0, 0, getEdgePos(), "last stage removed", false));
     341             :         }
     342        1768 :         (*myStep)->abort(this);
     343        1768 :         if (!proceed(MSNet::getInstance(), SIMSTEP)) {
     344          51 :             MSNet::getInstance()->getPersonControl().erase(this);
     345             :         }
     346             :     }
     347        1828 : }
     348             : 
     349             : 
     350             : void
     351          17 : MSTransportable::setSpeed(double speed) {
     352          45 :     for (MSTransportablePlan::const_iterator i = myStep; i != myPlan->end(); ++i) {
     353          28 :         (*i)->setSpeed(speed);
     354             :     }
     355          17 :     getSingularType().setMaxSpeed(speed);
     356          17 : }
     357             : 
     358             : 
     359             : bool
     360           0 : MSTransportable::replaceRoute(ConstMSRoutePtr newRoute, const std::string& /* info */, bool /* onInit */, int /* offset */, bool /* addRouteStops */, bool /* removeStops */, std::string* /* msgReturn */) {
     361           0 :     if (isPerson()) {
     362           0 :         static_cast<MSPerson*>(this)->reroute(newRoute->getEdges(), getPositionOnLane(), 0, 1);
     363           0 :         return true;
     364             :     }
     365             :     return false;
     366             : }
     367             : 
     368             : 
     369             : void
     370          78 : MSTransportable::replaceVehicleType(MSVehicleType* type) {
     371          78 :     const SUMOVehicleClass oldVClass = myVType->getVehicleClass();
     372          78 :     if (myVType->isVehicleSpecific()) {
     373           1 :         MSNet::getInstance()->getVehicleControl().removeVType(myVType);
     374             :     }
     375          78 :     if (isPerson()
     376          78 :             && type->getVehicleClass() != oldVClass
     377          12 :             && type->getVehicleClass() != SVC_PEDESTRIAN
     378          84 :             && !type->getParameter().wasSet(VTYPEPARS_VEHICLECLASS_SET)) {
     379          18 :         WRITE_WARNINGF(TL("Person '%' receives type '%' which implicitly uses unsuitable vClass '%'."), getID(), type->getID(), toString(type->getVehicleClass()));
     380             :     }
     381          78 :     myVType = type;
     382          78 : }
     383             : 
     384             : 
     385             : MSVehicleType&
     386          85 : MSTransportable::getSingularType() {
     387          85 :     if (myVType->isVehicleSpecific()) {
     388             :         return *myVType;
     389             :     }
     390         118 :     MSVehicleType* type = myVType->buildSingularType(myVType->getID() + "@" + getID());
     391          59 :     replaceVehicleType(type);
     392          59 :     return *type;
     393             : }
     394             : 
     395             : 
     396             : PositionVector
     397     1112555 : MSTransportable::getBoundingBox() const {
     398     1112555 :     PositionVector centerLine;
     399     1112555 :     const Position p = getPosition();
     400     1112555 :     const double angle = getAngle();
     401     1112555 :     const double length = getVehicleType().getLength();
     402     1112555 :     const Position back = p + Position(-cos(angle) * length, -sin(angle) * length);
     403     1112555 :     centerLine.push_back(p);
     404     1112555 :     centerLine.push_back(back);
     405     1112555 :     centerLine.move2side(0.5 * getVehicleType().getWidth());
     406             :     PositionVector result = centerLine;
     407     1112555 :     centerLine.move2side(-getVehicleType().getWidth());
     408     1112555 :     result.append(centerLine.reverse(), POSITION_EPS);
     409             :     //std::cout << " transp=" << getID() << " p=" << p << " angle=" << GeomHelper::naviDegree(angle) << " back=" << back << " result=" << result << "\n";
     410     1112555 :     return result;
     411     1112555 : }
     412             : 
     413             : 
     414             : std::string
     415           0 : MSTransportable::getStageSummary(int stageIndex) const {
     416             :     assert(stageIndex < (int)myPlan->size());
     417             :     assert(stageIndex >= 0);
     418           0 :     return (*myPlan)[stageIndex]->getStageSummary(myAmPerson);
     419             : }
     420             : 
     421             : 
     422             : const std::set<SUMOTrafficObject::NumericalID>
     423           0 : MSTransportable::getUpcomingEdgeIDs() const {
     424             :     std::set<SUMOTrafficObject::NumericalID> result;
     425           0 :     for (auto step = myStep; step != myPlan->end(); ++step) {
     426           0 :         for (const MSEdge* const e : (*step)->getEdges()) {
     427           0 :             result.insert(e->getNumericalID());
     428             :         }
     429             :     }
     430           0 :     return result;
     431             : }
     432             : 
     433             : 
     434             : bool
     435     3752329 : MSTransportable::hasArrived() const {
     436     3752329 :     return myStep == myPlan->end();
     437             : }
     438             : 
     439             : bool
     440       17929 : MSTransportable::hasDeparted() const {
     441       17929 :     return myPlan->size() > 0 && (myPlan->front()->getDeparted() >= 0 || myStep > myPlan->begin());
     442             : }
     443             : 
     444             : 
     445             : void
     446          41 : MSTransportable::rerouteParkingArea(MSStoppingPlace* orig, MSStoppingPlace* replacement) {
     447             :     // check whether the transportable was riding to the orignal stop
     448             :     // @note: parkingArea can currently not be set as myDestinationStop so we
     449             :     // check for stops on the edge instead
     450             : #ifdef DEBUG_PARKING
     451             :     std::cout << SIMTIME << " person=" << getID() << " rerouteParkingArea orig=" << orig->getID() << " replacement=" << replacement->getID() << "\n";
     452             : #endif
     453             :     assert(getCurrentStageType() == MSStageType::DRIVING);
     454          41 :     if (!myAmPerson) {
     455           0 :         WRITE_WARNING(TL("parkingAreaReroute not support for containers"));
     456           0 :         return;
     457             :     }
     458          41 :     if (getDestination() == &orig->getLane().getEdge()) {
     459          41 :         MSStageDriving* const stage = dynamic_cast<MSStageDriving*>(*myStep);
     460             :         assert(stage != 0);
     461             :         assert(stage->getVehicle() != 0);
     462             :         // adapt plan
     463          41 :         stage->setDestination(&replacement->getLane().getEdge(), replacement);
     464          41 :         stage->setArrivalPos((replacement->getBeginLanePosition() + replacement->getEndLanePosition()) / 2);
     465             : #ifdef DEBUG_PARKING
     466             :         std::cout << " set ride destination\n";
     467             : #endif
     468          41 :         if (myStep + 1 == myPlan->end()) {
     469             :             return;
     470             :         }
     471             :         // if the next step is a walk, adapt the route
     472          41 :         MSStage* nextStage = *(myStep + 1);
     473          41 :         if (nextStage->getStageType() == MSStageType::TRIP) {
     474          31 :             dynamic_cast<MSStageTrip*>(nextStage)->setOrigin(stage->getDestination());
     475             : #ifdef DEBUG_PARKING
     476             :             std::cout << " set subsequent trip origin\n";
     477             : #endif
     478          10 :         } else if (nextStage->getStageType() == MSStageType::WALKING) {
     479             : #ifdef DEBUG_PARKING
     480             :             std::cout << " replace subsequent walk with a trip\n";
     481             : #endif
     482           5 :             MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
     483           5 :                                                     nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
     484           5 :             removeStage(1);
     485           5 :             appendStage(newStage, 1);
     486           5 :         } else if (nextStage->getStageType() == MSStageType::WAITING) {
     487             : #ifdef DEBUG_PARKING
     488             :             std::cout << " add subsequent walk to reach stop\n";
     489             :             std::cout << "   arrivalPos=" << nextStage->getArrivalPos() << "\n";
     490             : #endif
     491           5 :             MSStageTrip* newStage = new MSStageTrip(stage->getDestination(), nullptr, nextStage->getDestination(),
     492           5 :                                                     nextStage->getDestinationStop(), -1, 0, "", -1, 1, getID(), 0, true, nextStage->getArrivalPos());
     493           5 :             appendStage(newStage, 1);
     494             :         }
     495             :         // if the plan contains another ride with the same vehicle from the same
     496             :         // parking area, adapt the preceeding walk to end at the replacement
     497          86 :         for (auto it = myStep + 2; it != myPlan->end(); it++) {
     498          55 :             MSStage* const futureStage = *it;
     499          55 :             MSStage* const prevStage = *(it - 1);
     500          55 :             if (futureStage->getStageType() == MSStageType::DRIVING) {
     501             :                 MSStageDriving* const ds = static_cast<MSStageDriving*>(futureStage);
     502             :                 // ride origin is set implicitly from the walk destination
     503             :                 ds->setOrigin(nullptr);
     504             :                 if (ds->getLines() == stage->getLines()
     505          10 :                         && prevStage->getDestination() == &orig->getLane().getEdge()) {
     506          10 :                     if (prevStage->getStageType() == MSStageType::TRIP) {
     507           5 :                         dynamic_cast<MSStageTrip*>(prevStage)->setDestination(stage->getDestination(), replacement);
     508             : #ifdef DEBUG_PARKING
     509             :                         std::cout << " replace later trip before ride (" << (it - myPlan->begin()) << ")\n";
     510             : #endif
     511           5 :                     } else if (prevStage->getStageType() == MSStageType::WALKING) {
     512             : #ifdef DEBUG_PARKING
     513             :                         std::cout << " replace later walk before ride (" << (it - myPlan->begin()) << ")\n";
     514             : #endif
     515           5 :                         MSStageTrip* newStage = new MSStageTrip(prevStage->getFromEdge(), nullptr, stage->getDestination(),
     516          10 :                                                                 replacement, -1, 0, "", -1, 1, getID(), 0, true, stage->getArrivalPos());
     517           5 :                         int prevStageRelIndex = (int)(it - 1 - myStep);
     518           5 :                         removeStage(prevStageRelIndex);
     519           5 :                         appendStage(newStage, prevStageRelIndex);
     520             :                     }
     521             :                     break;
     522             :                 }
     523             :             }
     524             :         }
     525             :     }
     526             : }
     527             : 
     528             : 
     529             : MSDevice*
     530      702131 : MSTransportable::getDevice(const std::type_info& type) const {
     531     1151243 :     for (MSTransportableDevice* const dev : myDevices) {
     532      972098 :         if (typeid(*dev) == type) {
     533             :             return dev;
     534             :         }
     535             :     }
     536             :     return nullptr;
     537             : }
     538             : 
     539             : 
     540             : void
     541          12 : MSTransportable::setJunctionModelParameter(const std::string& key, const std::string& value) {
     542          30 :     if (key == toString(SUMO_ATTR_JM_IGNORE_IDS) || key == toString(SUMO_ATTR_JM_IGNORE_TYPES)) {
     543           6 :         getParameter().parametersSet |= VEHPARS_JUNCTIONMODEL_PARAMS_SET;
     544           6 :         const_cast<SUMOVehicleParameter&>(getParameter()).setParameter(key, value);
     545             :         // checked in MSLink::ignoreFoe
     546             :     } else {
     547          18 :         throw InvalidArgument(getObjectType() + " '" + getID() + "' does not support junctionModel parameter '" + key + "'");
     548             :     }
     549           6 : }
     550             : 
     551             : 
     552             : double
     553           0 : MSTransportable::getSlope() const {
     554           0 :     const MSEdge* edge = getEdge();
     555           0 :     const double ep = getEdgePos();
     556           0 :     const double gp = edge->getLanes()[0]->interpolateLanePosToGeometryPos(ep);
     557           0 :     return edge->getLanes()[0]->getShape().slopeDegreeAtOffset(gp);
     558             : }
     559             : 
     560             : 
     561             : SUMOTime
     562           0 : MSTransportable::getWaitingTime(const bool /* accumulated */) const {
     563           0 :     return (*myStep)->getWaitingTime(MSNet::getInstance()->getCurrentTimeStep());
     564             : }
     565             : 
     566             : 
     567             : double
     568   102175549 : MSTransportable::getMaxSpeed() const {
     569   102175549 :     return MIN2(getVehicleType().getMaxSpeed(), getVehicleType().getDesiredMaxSpeed() * getChosenSpeedFactor());
     570             : }
     571             : 
     572             : 
     573             : SUMOVehicleClass
     574     1931395 : MSTransportable::getVClass() const {
     575     1931395 :     return getVehicleType().getVehicleClass();
     576             : }
     577             : 
     578             : 
     579             : int
     580           0 : MSTransportable::getRoutingMode() const {
     581             :     /// @todo: allow configuring routing mode
     582           0 :     return libsumo::ROUTING_MODE_DEFAULT;
     583             : }
     584             : 
     585             : void
     586          63 : MSTransportable::saveState(OutputDevice& out) {
     587             :     // this saves lots of departParameters which are only needed for transportables that did not yet depart
     588             :     // the parameters may hold the name of a vTypeDistribution but we are interested in the actual type
     589          63 :     myParameter->write(out, OptionsCont::getOptions(), myAmPerson ? SUMO_TAG_PERSON : SUMO_TAG_CONTAINER, getVehicleType().getID());
     590          63 :     if (!myParameter->wasSet(VEHPARS_SPEEDFACTOR_SET) && getChosenSpeedFactor() != 1) {
     591          60 :         out.setPrecision(MAX2(gPrecisionRandom, gPrecision));
     592          60 :         out.writeAttr(SUMO_ATTR_SPEEDFACTOR, getChosenSpeedFactor());
     593          60 :         out.setPrecision(gPrecision);
     594             :     }
     595          63 :     int stepIdx = (int)(myStep - myPlan->begin());
     596         147 :     for (auto it = myPlan->begin(); it != myStep; ++it) {
     597          84 :         const MSStageType st = (*it)->getStageType();
     598          84 :         if (st == MSStageType::TRIP || st == MSStageType::ACCESS) {
     599          27 :             stepIdx--;
     600             :         }
     601             :     }
     602          63 :     std::ostringstream state;
     603         126 :     state << myParameter->parametersSet << " " << stepIdx;
     604          63 :     (*myStep)->saveState(state);
     605          63 :     out.writeAttr(SUMO_ATTR_STATE, state.str());
     606             :     const MSStage* previous = nullptr;
     607         219 :     for (const MSStage* const stage : *myPlan) {
     608         156 :         stage->routeOutput(myAmPerson, out, false, previous);
     609             :         previous = stage;
     610             :     }
     611          63 :     out.closeTag();
     612          63 : }
     613             : 
     614             : 
     615             : void
     616          69 : MSTransportable::loadState(const std::string& state) {
     617          69 :     std::istringstream iss(state);
     618             :     int step;
     619          69 :     iss >> myParameter->parametersSet >> step;
     620          69 :     myStep = myPlan->begin() + step;
     621          69 :     (*myStep)->loadState(this, iss);
     622          69 : }
     623             : 
     624             : 
     625             : /****************************************************************************/

Generated by: LCOV version 1.14