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

Generated by: LCOV version 2.0-1