LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSTransportable.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 91.6 % 321 294
Test Date: 2025-11-13 15:38:19 Functions: 83.7 % 43 36

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

Generated by: LCOV version 2.0-1