LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSStageWalking.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.0 % 269 242
Test Date: 2026-05-24 16:29:35 Functions: 90.9 % 22 20

            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    MSStageWalking.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Laura Bieker
      19              : /// @date    Mon, 9 Jul 2001
      20              : ///
      21              : // A stage performing walking on a sequence of edges.
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <string>
      26              : #include <vector>
      27              : #include <utils/iodevices/OutputDevice.h>
      28              : #include <utils/options/OptionsCont.h>
      29              : #include <utils/common/ToString.h>
      30              : #include <utils/common/StringUtils.h>
      31              : #include <utils/geom/GeomHelper.h>
      32              : #include <utils/router/IntermodalNetwork.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSEdge.h>
      35              : #include <microsim/MSLane.h>
      36              : #include <microsim/transportables/MSTransportableControl.h>
      37              : #include <microsim/MSInsertionControl.h>
      38              : #include <microsim/MSEventControl.h>
      39              : #include <microsim/MSVehicle.h>
      40              : #include <microsim/MSVehicleControl.h>
      41              : #include <microsim/MSStoppingPlace.h>
      42              : #include <microsim/MSRouteHandler.h>
      43              : #include <microsim/devices/MSDevice_Tripinfo.h>
      44              : #include <microsim/devices/MSDevice_Taxi.h>
      45              : #include <microsim/trigger/MSTriggeredRerouter.h>
      46              : #include "MSPModel_Striping.h"
      47              : #include "MSStageTrip.h"
      48              : #include "MSPerson.h"
      49              : #include "MSStageWalking.h"
      50              : 
      51              : 
      52              : // ===========================================================================
      53              : // static member definition
      54              : // ===========================================================================
      55              : bool MSStageWalking::myWarnedInvalidTripinfo = false;
      56              : 
      57              : 
      58              : // ===========================================================================
      59              : // method definitions
      60              : // ===========================================================================
      61       229446 : MSStageWalking::MSStageWalking(const std::string& personID,
      62              :                                const ConstMSEdgeVector& route,
      63              :                                MSStoppingPlace* toStop,
      64              :                                SUMOTime walkingTime, double speed,
      65              :                                double departPos, double arrivalPos, double departPosLat, int departLane,
      66       229446 :                                const std::string& routeID) :
      67              :     MSStageMoving(MSStageType::WALKING, route, routeID, toStop, speed, departPos, arrivalPos, departPosLat, departLane),
      68       229446 :     myWalkingTime(walkingTime),
      69       229446 :     myExitTimes(nullptr),
      70       229446 :     myInternalDistance(0) {
      71       229446 :     myDepartPos = SUMOVehicleParameter::interpretEdgePos(departPos, route.front()->getLength(), SUMO_ATTR_DEPARTPOS,
      72       458892 :                   "person '" + personID + "' walking from edge '" + route.front()->getID() + "'");
      73       229446 :     myArrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, route.back()->getLength(), SUMO_ATTR_ARRIVALPOS,
      74       229446 :                    "person '" + personID + "' walking to edge '" + route.back()->getID() + "'");
      75       229446 :     if (walkingTime > 0) {
      76          111 :         mySpeed = computeAverageSpeed();
      77              :     }
      78       229446 : }
      79              : 
      80              : 
      81       458804 : MSStageWalking::~MSStageWalking() {
      82       229402 :     delete myExitTimes;
      83       458804 : }
      84              : 
      85              : 
      86              : MSStage*
      87        26486 : MSStageWalking::clone() const {
      88        26486 :     std::vector<const MSEdge*> route = myRoute;
      89        26486 :     double departPos = myDepartPos;
      90        26486 :     double arrivalPos = myArrivalPos;
      91        26486 :     int departLane = myDepartLane;
      92        26486 :     if (myRouteID != "" && MSRoute::distDictionary(myRouteID) != nullptr) {
      93          576 :         route = MSRoute::dictionary(myRouteID, MSRouteHandler::getParsingRNG())->getEdges();
      94          288 :         if (departPos > route[0]->getLength()) {
      95            0 :             WRITE_WARNINGF(TL("Adjusting departPos for cloned walk with routeDistribution '%'"), myRouteID);
      96            0 :             departPos = route[0]->getLength();
      97              :         }
      98          288 :         if (arrivalPos > route.back()->getLength()) {
      99            0 :             WRITE_WARNINGF(TL("Adjusting arrivalPos for cloned walk with routeDistribution '%'"), myRouteID);
     100            0 :             arrivalPos = route.back()->getLength();
     101              :         }
     102          288 :         if (departLane >= route[0]->getNumLanes()) {
     103            0 :             WRITE_WARNINGF(TL("Adjusting departLane for cloned walk with routeDistribution '%'"), myRouteID);
     104            0 :             departLane = route[0]->getNumLanes() - 1;
     105              :         }
     106              :     }
     107        26486 :     MSStage* clon = new MSStageWalking("dummyID", route, myDestinationStop, myWalkingTime, mySpeed, departPos, arrivalPos, myDepartPosLat, departLane, myRouteID);
     108        26486 :     clon->setParameters(*this);
     109        26486 :     return clon;
     110        26486 : }
     111              : 
     112              : 
     113              : void
     114       228510 : MSStageWalking::proceed(MSNet* net, MSTransportable* person, SUMOTime now, MSStage* previous) {
     115       228510 :     myDeparted = now;
     116       228510 :     myRouteStep = myRoute.begin();
     117       228510 :     myLastEdgeEntryTime = now;
     118       228510 :     if (myWalkingTime == 0) {
     119            0 :         if (!person->proceed(net, now)) {
     120            0 :             MSNet::getInstance()->getPersonControl().erase(person);
     121              :         }
     122            0 :         return;
     123              :     }
     124       228510 :     const OptionsCont& oc = OptionsCont::getOptions();
     125       228510 :     if (previous->getEdgePos(now) >= 0 && previous->getEdge() == *myRouteStep) {
     126              :         // we need to adapt to the arrival position of the vehicle unless we have an explicit access
     127       227812 :         myDepartPos = previous->getEdgePos(now);
     128       455624 :         if (oc.getString("pedestrian.model") == "jupedsim") {
     129            0 :             myDepartPosLat = previous->getEdgePosLat(now);
     130              :         }
     131       227812 :         if (myWalkingTime > 0) {
     132           93 :             mySpeed = computeAverageSpeed();
     133              :         }
     134              :     }
     135       228510 :     MSTransportableControl& pControl = net->getPersonControl();
     136       228510 :     myPState = pControl.getMovementModel()->add(person, this, now);
     137       228506 :     if (myPState == nullptr) {
     138            8 :         pControl.erase(person);
     139            8 :         return;
     140              :     }
     141       228498 :     if (previous->getStageType() != MSStageType::WALKING || previous->getEdge() != getEdge()) {
     142              :         // we only need new move reminders if we are walking a different edge (else it is probably a rerouting)
     143       226987 :         activateEntryReminders(person, true);
     144              :     }
     145       456996 :     if (oc.getBool("vehroute-output.exit-times")) {
     146          144 :         myExitTimes = new std::vector<SUMOTime>();
     147              :     }
     148       228498 :     (*myRouteStep)->addTransportable(person);
     149              : }
     150              : 
     151              : 
     152              : void
     153         1696 : MSStageWalking::abort(MSTransportable*) {
     154         1696 :     MSNet::getInstance()->getPersonControl().getMovementModel()->remove(myPState);
     155         1696 : }
     156              : 
     157              : 
     158              : void
     159           18 : MSStageWalking::setSpeed(double speed) {
     160           18 :     mySpeed = speed;
     161           18 : }
     162              : 
     163              : 
     164              : double
     165          204 : MSStageWalking::computeAverageSpeed() const {
     166          204 :     return walkDistance() / STEPS2TIME(myWalkingTime + 1); // avoid systematic rounding errors
     167              : }
     168              : 
     169              : 
     170              : bool
     171      1155618 : MSPerson::isJammed() const {
     172      1155618 :     MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
     173      1155618 :     if (stage != nullptr) {
     174      1155618 :         return stage->getPState()->isJammed();
     175              :     }
     176              :     return false;
     177              : }
     178              : 
     179              : 
     180              : double
     181       276170 : MSStageWalking::walkDistance(bool partial) const {
     182              :     double length = 0;
     183       276170 :     auto endIt = partial && myArrived < 0 ? myRouteStep + 1 : myRoute.end();
     184       750209 :     for (ConstMSEdgeVector::const_iterator i = myRoute.begin(); i != endIt; ++i) {
     185       474039 :         length += (*i)->getLength();
     186              :     }
     187       276170 :     if (myRoute.size() > 1 && MSNet::getInstance()->getPersonControl().getMovementModel()->usingInternalLanes()) {
     188       121462 :         if (myInternalDistance > 0) {
     189       109370 :             length += myInternalDistance;
     190              :         } else {
     191              :             // use lower bound for distance to pass the intersection
     192        48195 :             for (ConstMSEdgeVector::const_iterator i = myRoute.begin(); i != endIt - 1; ++i) {
     193        36103 :                 const MSEdge* fromEdge = *i;
     194        36103 :                 const MSEdge* toEdge = *(i + 1);
     195        36103 :                 const MSLane* from = getSidewalk<MSEdge, MSLane>(fromEdge);
     196        36103 :                 const MSLane* to = getSidewalk<MSEdge, MSLane>(toEdge);
     197              :                 Position fromPos;
     198              :                 Position toPos;
     199        36103 :                 if (from != nullptr && to != nullptr) {
     200        36103 :                     if (fromEdge->getToJunction() == toEdge->getFromJunction()) {
     201        36055 :                         fromPos = from->getShape().back();
     202        36055 :                         toPos = to->getShape().front();
     203           48 :                     } else if (fromEdge->getToJunction() == toEdge->getToJunction()) {
     204           26 :                         fromPos = from->getShape().back();
     205           26 :                         toPos = to->getShape().back();
     206           22 :                     } else if (fromEdge->getFromJunction() == toEdge->getFromJunction()) {
     207           10 :                         fromPos = from->getShape().front();
     208           10 :                         toPos = to->getShape().front();
     209           12 :                     } else if (fromEdge->getFromJunction() == toEdge->getToJunction()) {
     210           12 :                         fromPos = from->getShape().front();
     211           12 :                         toPos = to->getShape().back();
     212              :                     }
     213              :                     //std::cout << " from=" << from->getID() << " to=" << to->getID() << " junctionLength=" << fromPos.distanceTo2D(toPos) << "\n";
     214        36103 :                     length += fromPos.distanceTo2D(toPos);
     215              :                 }
     216              :             }
     217              :         }
     218              :     }
     219              :     // determine walking direction for depart and arrival
     220       276170 :     int dummy = 0;
     221       276170 :     const int departFwdArrivalDir = MSPModel::canTraverse(MSPModel::FORWARD, myRoute, dummy);
     222       276170 :     const int departBwdArrivalDir = MSPModel::canTraverse(MSPModel::BACKWARD, myRoute, dummy);
     223       276170 :     const bool mayStartForward = departFwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
     224       276170 :     const bool mayStartBackward = departBwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
     225       276170 :     const double arrivalPos = partial && myArrived < 0 ? getEdgePos(SIMSTEP) : myArrivalPos;
     226       276170 :     const double lengthFwd = (length - myDepartPos - (
     227              :                                   departFwdArrivalDir == MSPModel::BACKWARD
     228       276170 :                                   ? arrivalPos
     229       276170 :                                   : myRoute.back()->getLength() - arrivalPos));
     230       276170 :     const double lengthBwd = (length - (myRoute.front()->getLength() - myDepartPos) - (
     231              :                                   departBwdArrivalDir == MSPModel::BACKWARD
     232       276170 :                                   ? arrivalPos
     233       276170 :                                   : myRoute.back()->getLength() - arrivalPos));
     234              :     //std::cout << " length=" << length << " lengthFwd=" << lengthFwd << " lengthBwd=" << lengthBwd << " mayStartForward=" << mayStartForward << " mayStartBackward=" << mayStartBackward << "\n";
     235              : 
     236       276170 :     if (myRoute.size() == 1) {
     237       134397 :         if (myDepartPos > myArrivalPos) {
     238              :             length = lengthBwd;
     239              :         } else {
     240              :             length = lengthFwd;
     241              :         }
     242              :     } else {
     243       141773 :         if (mayStartForward && mayStartBackward) {
     244        11035 :             length = lengthFwd < lengthBwd ? lengthFwd : lengthBwd;
     245       130738 :         } else if (mayStartForward) {
     246              :             length = lengthFwd;
     247        49114 :         } else if (mayStartBackward) {
     248              :             length = lengthBwd;
     249              :         } else {
     250              :             length = lengthFwd;
     251              :         }
     252              :     }
     253              :     //std::cout << SIMTIME << " route=" << toString(myRoute)
     254              :     //    << " depPos=" << myDepartPos << " arPos=" << myArrivalPos
     255              :     //    << " dFwdADir=" << departFwdArrivalDir
     256              :     //    << " dBwdADir=" << departBwdArrivalDir
     257              :     //    << " lengthFwd=" << lengthFwd
     258              :     //    << " lengthBwd=" << lengthBwd
     259              :     //    << "\n";
     260              : 
     261       276170 :     return MAX2(POSITION_EPS, length);
     262              : }
     263              : 
     264              : 
     265              : SUMOTime
     266       110926 : MSStageWalking::getTimeLoss(const MSTransportable* transportable) const {
     267       110926 :     SUMOTime timeLoss = myArrived == -1 ? 0 : getDuration() - TIME2STEPS(walkDistance(true) / getMaxSpeed(transportable));
     268       110926 :     if (timeLoss < 0 && timeLoss > TIME2STEPS(-0.1)) {
     269              :         // avoid negative timeLoss due to rounding errors
     270              :         timeLoss = 0;
     271              :     }
     272       110926 :     return timeLoss;
     273              : }
     274              : 
     275              : 
     276              : void
     277        55463 : MSStageWalking::tripInfoOutput(OutputDevice& os, const MSTransportable* const person) const {
     278        55463 :     if (!myWarnedInvalidTripinfo && MSNet::getInstance()->getPersonControl().getMovementModel()->usingShortcuts()) {
     279            0 :         WRITE_WARNING(TL("The pedestrian model uses infrastructure which is not in the network, timeLoss and routeLength may be invalid."));
     280            0 :         myWarnedInvalidTripinfo = true;
     281              :     }
     282        55463 :     const double distance = walkDistance(true);
     283        55463 :     const double maxSpeed = getMaxSpeed(person);
     284        55463 :     const SUMOTime duration = myArrived - myDeparted;
     285        55463 :     const SUMOTime timeLoss = getTimeLoss(person);
     286        55463 :     MSDevice_Tripinfo::addPedestrianData(distance, duration, timeLoss);
     287        55463 :     os.openTag("walk");
     288        55463 :     os.writeAttr("depart", myDeparted >= 0 ? time2string(myDeparted) : "-1");
     289        55463 :     os.writeAttr("departPos", myDepartPos);
     290        55463 :     os.writeAttr("arrival", myArrived >= 0 ? time2string(myArrived) : "-1");
     291        55463 :     os.writeAttr("arrivalPos", myArrived >= 0 ? toString(myArrivalPos) : "-1");
     292       110661 :     os.writeAttr("duration", myDeparted < 0 ? "-1" :
     293        55198 :                  time2string(myArrived >= 0 ? duration : MSNet::getInstance()->getCurrentTimeStep() - myDeparted));
     294        55463 :     os.writeAttr("routeLength", myArrived >= 0 ? toString(distance) : "-1");
     295        55463 :     os.writeAttr("timeLoss", time2string(timeLoss));
     296        55463 :     os.writeAttr("maxSpeed", maxSpeed);
     297        55463 :     os.writeAttr("waitingTime", time2string(getTotalWaitingTime()));
     298        55463 :     os.closeTag();
     299        55463 : }
     300              : 
     301              : 
     302              : void
     303         2426 : MSStageWalking::routeOutput(const bool /* isPerson */, OutputDevice& os, const bool withRouteLength, const MSStage* const /* previous */, const bool withTiming, const bool saveState) const {
     304         2426 :     os.openTag("walk").writeAttr(SUMO_ATTR_EDGES, myRoute);
     305         2426 :     std::string comment = "";
     306         2426 :     if (myDestinationStop != nullptr) {
     307          453 :         os.writeAttr(toString(myDestinationStop->getElement()), myDestinationStop->getID());
     308          453 :         if (myDestinationStop->getMyName() != "") {
     309          231 :             comment =  " <!-- " + StringUtils::escapeXML(myDestinationStop->getMyName(), true) + " -->";
     310              :         }
     311         1973 :     } else if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
     312          166 :         os.writeAttr(SUMO_ATTR_ARRIVALPOS, myArrivalPos);
     313              :     }
     314         2426 :     if (myWalkingTime > 0) {
     315            0 :         os.writeAttr(SUMO_ATTR_DURATION, time2string(myWalkingTime));
     316         2426 :     } else if (mySpeed > 0) {
     317           24 :         os.writeAttr(SUMO_ATTR_SPEED, mySpeed);
     318              :     }
     319         2426 :     if (withRouteLength) {
     320           36 :         if (myDeparted >= 0) {
     321           36 :             os.writeAttr("routeLength", walkDistance(true));
     322              :         } else {
     323            0 :             os.writeAttr("routeLength", "-1");
     324              :         }
     325              :     }
     326         2426 :     if (myExitTimes != nullptr) {
     327              :         std::vector<std::string> exits;
     328          562 :         for (SUMOTime t : *myExitTimes) {
     329          780 :             exits.push_back(time2string(t));
     330              :         }
     331          344 :         std::vector<std::string> missing(MAX2(0, (int)myRoute.size() - (int)myExitTimes->size()), "-1");
     332          172 :         exits.insert(exits.end(), missing.begin(), missing.end());
     333          172 :         os.writeAttr("exitTimes", exits);
     334          172 :     }
     335         2426 :     if (withTiming) {
     336          194 :         os.writeAttr(SUMO_ATTR_STARTED, myDeparted >= 0 ? time2string(myDeparted) : "-1");
     337          194 :         os.writeAttr(SUMO_ATTR_ENDED, myArrived >= 0 ? time2string(myArrived) : "-1");
     338              :     }
     339         4852 :     if (OptionsCont::getOptions().getBool("vehroute-output.cost")) {
     340          105 :         os.writeAttr(SUMO_ATTR_COST, getCosts());
     341              :     }
     342         2426 :     if (saveState && getTotalWaitingTime() > 0) {
     343            2 :         os.writeAttr("waitingTime", time2string(getTotalWaitingTime()));
     344              :     }
     345         2426 :     os.closeTag(comment);
     346         2426 : }
     347              : 
     348              : 
     349              : bool
     350      2631721 : MSStageWalking::moveToNextEdge(MSTransportable* person, SUMOTime currentTime, int prevDir, MSEdge* nextInternal, const bool isReplay) {
     351      2631721 :     ((MSEdge*)getEdge())->removeTransportable(person);
     352      2631721 :     const MSLane* lane = getSidewalk<MSEdge, MSLane>(getEdge());
     353              :     const bool arrived = myRouteStep == myRoute.end() - 1;
     354      2631721 :     if (lane != nullptr) {
     355      2609842 :         const double tl = person->getVehicleType().getLength();
     356              :         const double lastPos = (arrived
     357      2609842 :                                 ? (prevDir == MSPModel::FORWARD
     358      3692877 :                                    ? getArrivalPos() + tl
     359      1758183 :                                    : getArrivalPos() - tl)
     360       675148 :                                 : person->getPositionOnLane());
     361      2609842 :         activateLeaveReminders(person, lane, lastPos, currentTime, arrived);
     362              :     }
     363      2631721 :     if (myExitTimes != nullptr && nextInternal == nullptr) {
     364          374 :         myExitTimes->push_back(currentTime);
     365              :     }
     366              :     myMoveReminders.clear();
     367      2631721 :     myLastEdgeEntryTime = currentTime;
     368              :     //std::cout << SIMTIME << " moveToNextEdge person=" << person->getID() << "\n";
     369      2631721 :     if (myCurrentInternalEdge != nullptr) {
     370       365420 :         myInternalDistance += (myPState->getPathLength() == 0 ? myCurrentInternalEdge->getLength() : myPState->getPathLength());
     371              :     }
     372      2631721 :     if (arrived) {
     373      1934720 :         MSPerson* p = dynamic_cast<MSPerson*>(person);
     374      1934720 :         if (!isReplay && p->hasInfluencer() && p->getInfluencer().isRemoteControlled()) {
     375      1716317 :             myCurrentInternalEdge = nextInternal;
     376      1716317 :             ((MSEdge*) getEdge())->addTransportable(person);
     377      1716317 :             return false;
     378              :         }
     379       218403 :         if (myDestinationStop != nullptr) {
     380        33583 :             myDestinationStop->addTransportable(person);
     381              :         }
     382       218403 :         if (isReplay) {
     383              :             // cannot do this in the replay device because the person might get deleted below
     384           40 :             MSNet::getInstance()->getPersonControl().getMovementModel()->remove(myPState);
     385              :         }
     386       218403 :         if (!person->proceed(MSNet::getInstance(), currentTime)) {
     387       211882 :             MSNet::getInstance()->getPersonControl().erase(person);
     388              :         }
     389              :         //std::cout << " end walk. myRouteStep=" << (*myRouteStep)->getID() << "\n";
     390       218403 :         return true;
     391              :     } else {
     392       697001 :         if (nextInternal == nullptr) {
     393              :             ++myRouteStep;
     394              :         }
     395       697001 :         myCurrentInternalEdge = nextInternal;
     396       697001 :         ((MSEdge*) getEdge())->addTransportable(person);
     397       697001 :         return false;
     398              :     }
     399              : }
     400              : 
     401              : 
     402              : void
     403      2639883 : MSStageWalking::activateEntryReminders(MSTransportable* person, const bool isDepart) {
     404      2639883 :     const MSLane* const nextLane = getSidewalk<MSEdge, MSLane>(getEdge());
     405      2639883 :     if (nextLane != nullptr) {
     406      3459659 :         for (MSMoveReminder* const rem : nextLane->getMoveReminders()) {
     407      1380735 :             if (rem->notifyEnter(*person, isDepart ? MSMoveReminder::NOTIFICATION_DEPARTED : MSMoveReminder::NOTIFICATION_JUNCTION, nextLane)) {
     408        18563 :                 myMoveReminders.push_back(rem);
     409              :             }
     410              :         }
     411              :     }
     412      5279766 :     if (hasParameter("rerouter")) {
     413              :         double minDist = std::numeric_limits<double>::max();
     414              :         MSTriggeredRerouter* nearest = nullptr;
     415          190 :         for (MSMoveReminder* const rem : myMoveReminders) {
     416          120 :             MSTriggeredRerouter* rerouter = dynamic_cast<MSTriggeredRerouter*>(rem);
     417          120 :             if (rerouter != nullptr) {
     418           70 :                 const double dist2 = rerouter->getPosition().distanceSquaredTo2D(person->getPosition());
     419           70 :                 if (dist2 < minDist) {
     420              :                     nearest = rerouter;
     421              :                     minDist = dist2;
     422              :                 }
     423              :             }
     424              :         }
     425           70 :         if (nearest != nullptr) {
     426           70 :             nearest->triggerRouting(*person, MSMoveReminder::NOTIFICATION_JUNCTION);
     427              :         }
     428              :         // TODO maybe removal of the reminders? Or can we rely on movetonextedge to clean everything up?
     429              :     }
     430      2639883 : }
     431              : 
     432              : 
     433              : void
     434            0 : MSStageWalking::activateMoveReminders(MSTransportable* person, double oldPos, double newPos, double newSpeed) {
     435            0 :     for (std::vector<MSMoveReminder*>::iterator rem = myMoveReminders.begin(); rem != myMoveReminders.end();) {
     436            0 :         if ((*rem)->notifyMove(*person, oldPos, newPos, newSpeed)) {
     437              :             ++rem;
     438              :         } else {
     439            0 :             rem = myMoveReminders.erase(rem);
     440              :         }
     441              :     }
     442            0 : }
     443              : 
     444              : 
     445              : void
     446      2609842 : MSStageWalking::activateLeaveReminders(MSTransportable* person, const MSLane* lane, double lastPos, SUMOTime t, bool arrived) {
     447      2609842 :     MSMoveReminder::Notification notification = arrived ? MSMoveReminder::NOTIFICATION_ARRIVED : MSMoveReminder::NOTIFICATION_JUNCTION;
     448      2627281 :     for (MSMoveReminder* const rem : myMoveReminders) {
     449        17439 :         rem->updateDetector(*person, 0.0, lane->getLength(), myLastEdgeEntryTime, t, t, true);
     450        17439 :         rem->notifyLeave(*person, lastPos, notification);
     451              :     }
     452      2609842 : }
     453              : 
     454              : 
     455              : int
     456       449238 : MSStageWalking::getRoutePosition() const {
     457       449238 :     return (int)(myRouteStep - myRoute.begin());
     458              : }
     459              : 
     460              : 
     461              : double
     462     21690450 : MSStageWalking::getMaxSpeed(const MSTransportable* const person) const {
     463     21690450 :     return mySpeed >= 0 ? mySpeed : person->getMaxSpeed();
     464              : }
     465              : 
     466              : std::string
     467            0 : MSStageWalking::getStageSummary(const bool /* isPerson */) const {
     468            0 :     const std::string dest = (getDestinationStop() == nullptr ?
     469            0 :                               " edge '" + getDestination()->getID() + "'" :
     470            0 :                               " stop '" + getDestinationStop()->getID() + "'" + (
     471            0 :                                   getDestinationStop()->getMyName() != "" ? " (" + getDestinationStop()->getMyName() + ")" : ""));
     472            0 :     return "walking to " + dest;
     473              : }
     474              : 
     475              : 
     476              : void
     477           32 : MSStageWalking::saveState(std::ostringstream& out, MSTransportable* /*transportable*/) {
     478           64 :     out << " " << myDeparted << " " << (myRouteStep - myRoute.begin()) << " " << myLastEdgeEntryTime;
     479           32 :     if (myExitTimes != nullptr) {
     480           12 :         out << " " << myExitTimes->size();
     481           18 :         for (SUMOTime t : *myExitTimes) {
     482              :             out << " " << t;
     483              :         }
     484              :     } else {
     485           20 :         out << " " << -1;
     486              :     }
     487           32 :     myPState->saveState(out);
     488           32 : }
     489              : 
     490              : 
     491              : void
     492           36 : MSStageWalking::loadState(MSTransportable* transportable, std::istringstream& state) {
     493              :     int stepIdx;
     494           36 :     state >> myDeparted >> stepIdx >> myLastEdgeEntryTime;
     495              :     int exitTimesSize;
     496           36 :     state >> exitTimesSize;
     497           36 :     if (exitTimesSize >= 0) {
     498           12 :         myExitTimes = new std::vector<SUMOTime>();
     499              :         SUMOTime t;
     500           18 :         for (int i = 0; i < exitTimesSize; i++) {
     501              :             state >> t;
     502            6 :             myExitTimes->push_back(t);
     503              :         }
     504           24 :         if (!OptionsCont::getOptions().getBool("vehroute-output.exit-times")) {
     505            0 :             delete myExitTimes;
     506            0 :             myExitTimes = nullptr;
     507              :         }
     508              :     }
     509           36 :     myRouteStep = myRoute.begin() + stepIdx;
     510           36 :     myPState = MSNet::getInstance()->getPersonControl().getMovementModel()->loadState(transportable, this, state);
     511           36 :     if (myPState->getLane() && !myPState->getLane()->isNormal()) {
     512            1 :         myCurrentInternalEdge = &myPState->getLane()->getEdge();
     513            1 :         myCurrentInternalEdge->addTransportable(transportable);
     514              :     } else {
     515           35 :         (*myRouteStep)->addTransportable(transportable);
     516              :     }
     517           36 : }
     518              : 
     519              : 
     520              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1