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

Generated by: LCOV version 2.0-1