LCOV - code coverage report
Current view: top level - src/libsumo - Person.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 446 611 73.0 %
Date: 2024-04-27 15:34:54 Functions: 62 97 63.9 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2017-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    Person.cpp
      15             : /// @author  Leonhard Luecken
      16             : /// @date    15.09.2017
      17             : ///
      18             : // C++ TraCI client API implementation
      19             : /****************************************************************************/
      20             : #include <config.h>
      21             : 
      22             : #include <microsim/transportables/MSTransportableControl.h>
      23             : #include <microsim/MSVehicleControl.h>
      24             : #include <microsim/MSEdge.h>
      25             : #include <microsim/MSLane.h>
      26             : #include <microsim/MSNet.h>
      27             : #include <microsim/MSStoppingPlace.h>
      28             : #include <microsim/transportables/MSPModel.h>
      29             : #include <microsim/transportables/MSPerson.h>
      30             : #include <microsim/transportables/MSStageDriving.h>
      31             : #include <microsim/transportables/MSStageWaiting.h>
      32             : #include <microsim/transportables/MSStageWalking.h>
      33             : #include <microsim/devices/MSDevice_Taxi.h>
      34             : #include <microsim/devices/MSDispatch_TraCI.h>
      35             : #include <libsumo/TraCIConstants.h>
      36             : #include <utils/geom/GeomHelper.h>
      37             : #include <utils/common/StringTokenizer.h>
      38             : #include <utils/common/SUMOTime.h>
      39             : #include <utils/emissions/PollutantsInterface.h>
      40             : #include <utils/router/PedestrianRouter.h>
      41             : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      42             : #include "Helper.h"
      43             : #include "VehicleType.h"
      44             : #include "Person.h"
      45             : 
      46             : #define FAR_AWAY 1000.0
      47             : 
      48             : //#define DEBUG_MOVEXY
      49             : //#define DEBUG_MOVEXY_ANGLE
      50             : 
      51             : namespace libsumo {
      52             : // ===========================================================================
      53             : // static member initializations
      54             : // ===========================================================================
      55             : SubscriptionResults Person::mySubscriptionResults;
      56             : ContextSubscriptionResults Person::myContextSubscriptionResults;
      57             : 
      58             : 
      59             : // ===========================================================================
      60             : // static member definitions
      61             : // ===========================================================================
      62             : std::vector<std::string>
      63       73069 : Person::getIDList() {
      64       73069 :     MSTransportableControl& c = MSNet::getInstance()->getPersonControl();
      65             :     std::vector<std::string> ids;
      66      194508 :     for (MSTransportableControl::constVehIt i = c.loadedBegin(); i != c.loadedEnd(); ++i) {
      67      121441 :         if (i->second->getCurrentStageType() != MSStageType::WAITING_FOR_DEPART) {
      68      121419 :             ids.push_back(i->first);
      69             :         }
      70             :     }
      71       73067 :     return ids;
      72           0 : }
      73             : 
      74             : 
      75             : int
      76          26 : Person::getIDCount() {
      77          26 :     return MSNet::getInstance()->getPersonControl().size();
      78             : }
      79             : 
      80             : 
      81             : TraCIPosition
      82      158684 : Person::getPosition(const std::string& personID, const bool includeZ) {
      83      158684 :     return Helper::makeTraCIPosition(getPerson(personID)->getPosition(), includeZ);
      84             : }
      85             : 
      86             : 
      87             : TraCIPosition
      88           4 : Person::getPosition3D(const std::string& personID) {
      89           4 :     return Helper::makeTraCIPosition(getPerson(personID)->getPosition(), true);
      90             : }
      91             : 
      92             : 
      93             : double
      94         135 : Person::getAngle(const std::string& personID) {
      95         135 :     return GeomHelper::naviDegree(getPerson(personID)->getAngle());
      96             : }
      97             : 
      98             : 
      99             : double
     100          13 : Person::getSlope(const std::string& personID) {
     101          13 :     MSPerson* person = getPerson(personID);
     102          13 :     const double ep = person->getEdgePos();
     103          13 :     const MSLane* lane = getSidewalk<MSEdge, MSLane>(person->getEdge());
     104          13 :     if (lane == nullptr) {
     105           0 :         lane = person->getEdge()->getLanes()[0];
     106             :     }
     107             :     const double gp = lane->interpolateLanePosToGeometryPos(ep);
     108          13 :     return lane->getShape().slopeDegreeAtOffset(gp);
     109             : }
     110             : 
     111             : 
     112             : double
     113          41 : Person::getSpeed(const std::string& personID) {
     114          41 :     return getPerson(personID)->getSpeed();
     115             : }
     116             : 
     117             : 
     118             : std::string
     119        1478 : Person::getRoadID(const std::string& personID) {
     120        1478 :     return getPerson(personID)->getEdge()->getID();
     121             : }
     122             : 
     123             : 
     124             : std::string
     125         310 : Person::getLaneID(const std::string& personID) {
     126         620 :     return Named::getIDSecure(getPerson(personID)->getLane(), "");
     127             : }
     128             : 
     129             : 
     130             : double
     131         131 : Person::getLanePosition(const std::string& personID) {
     132         131 :     return getPerson(personID)->getEdgePos();
     133             : }
     134             : 
     135             : std::vector<TraCIReservation>
     136        5323 : Person::getTaxiReservations(int onlyNew) {
     137             :     std::vector<TraCIReservation> result;
     138             :     MSDispatch* dispatcher = MSDevice_Taxi::getDispatchAlgorithm();
     139        5323 :     if (dispatcher != nullptr) {
     140        5323 :         MSDispatch_TraCI* traciDispatcher = dynamic_cast<MSDispatch_TraCI*>(dispatcher);
     141        5323 :         if (traciDispatcher == nullptr) {
     142           0 :             throw TraCIException("device.taxi.dispatch-algorithm 'traci' has not been loaded");
     143             :         }
     144        8511 :         for (Reservation* res : dispatcher->getReservations()) {
     145        3188 :             if (filterReservation(onlyNew, res, result)) {
     146        1592 :                 if (res->state == Reservation::NEW) {
     147         537 :                     res->state = Reservation::RETRIEVED;
     148             :                 }
     149             :             }
     150             :         }
     151        5323 :         const bool includeRunning = onlyNew == 0 || (onlyNew & (Reservation::ASSIGNED | Reservation::ONBOARD)) != 0;
     152             :         if (includeRunning) {
     153        9319 :             for (const Reservation* res : dispatcher->getRunningReservations()) {
     154        6105 :                 filterReservation(onlyNew, res, result);
     155             :             }
     156             :         }
     157             :     }
     158        5323 :     std::sort(result.begin(), result.end(), reservation_by_id_sorter());
     159        5323 :     return result;
     160           0 : }
     161             : 
     162             : int
     163        9787 : Person::reservation_by_id_sorter::operator()(const TraCIReservation& r1, const TraCIReservation& r2) const {
     164        9787 :     return r1.id < r2.id;
     165             : }
     166             : 
     167             : 
     168             : std::string
     169           6 : Person::splitTaxiReservation(std::string reservationID, const std::vector<std::string>& personIDs) {
     170             :     MSDispatch* dispatcher = MSDevice_Taxi::getDispatchAlgorithm();
     171           6 :     if (dispatcher != nullptr) {
     172           6 :         MSDispatch_TraCI* traciDispatcher = dynamic_cast<MSDispatch_TraCI*>(dispatcher);
     173           6 :         if (traciDispatcher != nullptr) {
     174          18 :             return traciDispatcher->splitReservation(reservationID, personIDs);
     175             :         }
     176             :     }
     177           0 :     throw TraCIException("device.taxi.dispatch-algorithm 'traci' has not been loaded");
     178             : }
     179             : 
     180             : bool
     181        9293 : Person::filterReservation(int onlyNew, const Reservation* res, std::vector<libsumo::TraCIReservation>& reservations) {
     182        9293 :     if (onlyNew != 0 && (onlyNew & res->state) == 0) {
     183             :         return false;
     184             :     }
     185             :     std::vector<std::string> personIDs;
     186       14046 :     for (const MSTransportable* p : res->persons) {
     187        7038 :         personIDs.push_back(p->getID());
     188             :     }
     189        7008 :     std::sort(personIDs.begin(), personIDs.end());
     190        7008 :     reservations.push_back(TraCIReservation(res->id,
     191             :                                             personIDs,
     192        7008 :                                             res->group,
     193        7008 :                                             res->from->getID(),
     194        7008 :                                             res->to->getID(),
     195        7008 :                                             res->fromPos,
     196        7008 :                                             res->toPos,
     197        7008 :                                             STEPS2TIME(res->pickupTime),
     198        7008 :                                             STEPS2TIME(res->reservationTime),
     199        7008 :                                             res->state
     200             :                                            ));
     201             :     return true;
     202        7008 : }
     203             : 
     204             : 
     205             : TraCIColor
     206          15 : Person::getColor(const std::string& personID) {
     207          15 :     const RGBColor& col = getPerson(personID)->getParameter().color;
     208             :     TraCIColor tcol;
     209          15 :     tcol.r = col.red();
     210          15 :     tcol.g = col.green();
     211          15 :     tcol.b = col.blue();
     212          15 :     tcol.a = col.alpha();
     213          15 :     return tcol;
     214             : }
     215             : 
     216             : 
     217             : std::string
     218        2178 : Person::getTypeID(const std::string& personID) {
     219        2178 :     return getPerson(personID)->getVehicleType().getID();
     220             : }
     221             : 
     222             : 
     223             : double
     224        1198 : Person::getWaitingTime(const std::string& personID) {
     225        1198 :     return getPerson(personID)->getWaitingSeconds();
     226             : }
     227             : 
     228             : 
     229             : std::string
     230         145 : Person::getNextEdge(const std::string& personID) {
     231         145 :     return getPerson(personID)->getNextEdge();
     232             : }
     233             : 
     234             : 
     235             : std::vector<std::string>
     236        1370 : Person::getEdges(const std::string& personID, int nextStageIndex) {
     237        1370 :     MSTransportable* p = getPerson(personID);
     238        1370 :     if (nextStageIndex >= p->getNumRemainingStages()) {
     239           0 :         throw TraCIException("The stage index must be lower than the number of remaining stages.");
     240             :     }
     241        1370 :     if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
     242           0 :         throw TraCIException("The negative stage index must refer to a valid previous stage.");
     243             :     }
     244             :     std::vector<std::string> edgeIDs;
     245        3631 :     for (auto& e : p->getNextStage(nextStageIndex)->getEdges()) {
     246        2261 :         if (e != nullptr) {
     247        2261 :             edgeIDs.push_back(e->getID());
     248             :         }
     249             :     }
     250        1370 :     return edgeIDs;
     251           0 : }
     252             : 
     253             : 
     254             : TraCIStage
     255        1022 : Person::getStage(const std::string& personID, int nextStageIndex) {
     256        1022 :     MSTransportable* p = getPerson(personID);
     257        2040 :     TraCIStage result;
     258        1020 :     if (nextStageIndex >= p->getNumRemainingStages()) {
     259          12 :         throw TraCIException("The stage index must be lower than the number of remaining stages.");
     260             :     }
     261        1014 :     if (nextStageIndex < (p->getNumRemainingStages() - p->getNumStages())) {
     262         154 :         throw TraCIException("The negative stage index " + toString(nextStageIndex) + " must refer to a valid previous stage.");
     263             :     }
     264             :     //stageType, arrivalPos, edges, destStop, vType, and description can be retrieved directly from the base Stage class.
     265             :     MSStage* stage = p->getNextStage(nextStageIndex);
     266         937 :     result.type = (int)stage->getStageType();
     267         937 :     result.arrivalPos = stage->getArrivalPos();
     268        2674 :     for (auto e : stage->getEdges()) {
     269        1737 :         if (e != nullptr) {
     270        1725 :             result.edges.push_back(e->getID());
     271             :         }
     272             :     }
     273             :     MSStoppingPlace* destinationStop = stage->getDestinationStop();
     274         937 :     if (destinationStop != nullptr) {
     275         585 :         result.destStop = destinationStop->getID();
     276             :     }
     277         937 :     result.description = stage->getStageDescription(p->isPerson());
     278         937 :     result.length = stage->getDistance();
     279         937 :     if (result.length == -1.) {
     280          89 :         result.length = INVALID_DOUBLE_VALUE;
     281             :     }
     282         937 :     result.departPos = INVALID_DOUBLE_VALUE;
     283         937 :     result.cost = INVALID_DOUBLE_VALUE;
     284         937 :     result.depart = stage->getDeparted() >= 0 ? STEPS2TIME(stage->getDeparted()) : INVALID_DOUBLE_VALUE;
     285         937 :     result.travelTime = INVALID_DOUBLE_VALUE;
     286         937 :     if (stage->getArrived() >= 0) {
     287         207 :         result.travelTime = STEPS2TIME(stage->getArrived() - stage->getDeparted());
     288         730 :     } else if (stage->getDeparted() >= 0) {
     289         561 :         result.travelTime = STEPS2TIME(SIMSTEP - stage->getDeparted());
     290             :     }
     291             : 
     292             :     // Some stage type dependant attributes
     293         937 :     switch (stage->getStageType()) {
     294         667 :         case MSStageType::DRIVING: {
     295             :             MSStageDriving* const drivingStage = static_cast<MSStageDriving*>(stage);
     296        1334 :             result.vType = drivingStage->getVehicleType();
     297         667 :             result.intended = drivingStage->getIntendedVehicleID();
     298         667 :             if (result.depart < 0 && drivingStage->getIntendedDepart() >= 0) {
     299           0 :                 result.depart = STEPS2TIME(drivingStage->getIntendedDepart());
     300             :             }
     301             :             const std::set<std::string> lines = drivingStage->getLines();
     302        1334 :             for (auto line = lines.begin(); line != lines.end(); line++) {
     303         667 :                 if (line != lines.begin()) {
     304           0 :                     result.line += " ";
     305             :                 }
     306         667 :                 result.line += *line;
     307             :             }
     308             :             break;
     309             :         }
     310          91 :         case MSStageType::WALKING: {
     311             :             auto* walkingStage = (MSStageWalking*) stage;
     312          91 :             result.departPos = walkingStage->getDepartPos();
     313          91 :             break;
     314             :         }
     315          25 :         case MSStageType::WAITING: {
     316             :             auto* waitingStage = (MSStageWaiting*) stage;
     317          25 :             if (waitingStage->getDuration() > 0) {
     318          12 :                 result.travelTime = STEPS2TIME(waitingStage->getDuration());
     319             :             }
     320             :             break;
     321             :         }
     322             :         default:
     323             :             break;
     324             :     }
     325         937 :     return result;
     326          83 : }
     327             : 
     328             : 
     329             : int
     330         228 : Person::getRemainingStages(const std::string& personID) {
     331         228 :     return getPerson(personID)->getNumRemainingStages();
     332             : }
     333             : 
     334             : 
     335             : std::string
     336          13 : Person::getVehicle(const std::string& personID) {
     337          13 :     const SUMOVehicle* veh = getPerson(personID)->getVehicle();
     338          13 :     if (veh == nullptr) {
     339          13 :         return "";
     340             :     } else {
     341             :         return veh->getID();
     342             :     }
     343             : }
     344             : 
     345             : 
     346             : std::string
     347         895 : Person::getParameter(const std::string& personID, const std::string& param) {
     348        1789 :     return getPerson(personID)->getParameter().getParameter(param, "");
     349             : }
     350             : 
     351             : 
     352          56 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Person)
     353             : 
     354             : 
     355             : std::string
     356           0 : Person::getEmissionClass(const std::string& personID) {
     357           0 :     return PollutantsInterface::getName(getPerson(personID)->getVehicleType().getEmissionClass());
     358             : }
     359             : 
     360             : 
     361             : std::string
     362           0 : Person::getShapeClass(const std::string& personID) {
     363           0 :     return getVehicleShapeName(getPerson(personID)->getVehicleType().getGuiShape());
     364             : }
     365             : 
     366             : 
     367             : double
     368           4 : Person::getLength(const std::string& personID) {
     369           4 :     return getPerson(personID)->getVehicleType().getLength();
     370             : }
     371             : 
     372             : 
     373             : double
     374          12 : Person::getSpeedFactor(const std::string& personID) {
     375          12 :     return getPerson(personID)->getChosenSpeedFactor();
     376             : }
     377             : 
     378             : 
     379             : double
     380           0 : Person::getAccel(const std::string& personID) {
     381           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getMaxAccel();
     382             : }
     383             : 
     384             : 
     385             : double
     386           0 : Person::getDecel(const std::string& personID) {
     387           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getMaxDecel();
     388             : }
     389             : 
     390             : 
     391           0 : double Person::getEmergencyDecel(const std::string& personID) {
     392           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getEmergencyDecel();
     393             : }
     394             : 
     395             : 
     396           0 : double Person::getApparentDecel(const std::string& personID) {
     397           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getApparentDecel();
     398             : }
     399             : 
     400             : 
     401           0 : double Person::getActionStepLength(const std::string& personID) {
     402           0 :     return getPerson(personID)->getVehicleType().getActionStepLengthSecs();
     403             : }
     404             : 
     405             : 
     406             : double
     407           0 : Person::getTau(const std::string& personID) {
     408           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getHeadwayTime();
     409             : }
     410             : 
     411             : 
     412             : double
     413           0 : Person::getImperfection(const std::string& personID) {
     414           0 :     return getPerson(personID)->getVehicleType().getCarFollowModel().getImperfection();
     415             : }
     416             : 
     417             : 
     418             : double
     419           0 : Person::getSpeedDeviation(const std::string& personID) {
     420           0 :     return getPerson(personID)->getVehicleType().getSpeedFactor().getParameter()[1];
     421             : }
     422             : 
     423             : 
     424             : std::string
     425           0 : Person::getVehicleClass(const std::string& personID) {
     426           0 :     return toString(getPerson(personID)->getVehicleType().getVehicleClass());
     427             : }
     428             : 
     429             : 
     430             : double
     431           4 : Person::getMinGap(const std::string& personID) {
     432           4 :     return getPerson(personID)->getVehicleType().getMinGap();
     433             : }
     434             : 
     435             : 
     436             : double
     437           0 : Person::getMinGapLat(const std::string& personID) {
     438           0 :     return getPerson(personID)->getVehicleType().getMinGapLat();
     439             : }
     440             : 
     441             : 
     442             : double
     443          12 : Person::getMaxSpeed(const std::string& personID) {
     444          12 :     return getPerson(personID)->getMaxSpeed();
     445             : }
     446             : 
     447             : 
     448             : double
     449           0 : Person::getMaxSpeedLat(const std::string& personID) {
     450           0 :     return getPerson(personID)->getVehicleType().getMaxSpeedLat();
     451             : }
     452             : 
     453             : 
     454             : std::string
     455           0 : Person::getLateralAlignment(const std::string& personID) {
     456           0 :     return toString(getPerson(personID)->getVehicleType().getPreferredLateralAlignment());
     457             : }
     458             : 
     459             : 
     460             : double
     461           4 : Person::getWidth(const std::string& personID) {
     462           4 :     return getPerson(personID)->getVehicleType().getWidth();
     463             : }
     464             : 
     465             : 
     466             : double
     467           0 : Person::getHeight(const std::string& personID) {
     468           0 :     return getPerson(personID)->getVehicleType().getHeight();
     469             : }
     470             : 
     471             : 
     472             : int
     473           0 : Person::getPersonCapacity(const std::string& personID) {
     474           0 :     return getPerson(personID)->getVehicleType().getPersonCapacity();
     475             : }
     476             : 
     477             : 
     478             : double
     479           4 : Person::getBoardingDuration(const std::string& personID) {
     480           4 :     return STEPS2TIME(getPerson(personID)->getVehicleType().getBoardingDuration(true));
     481             : }
     482             : 
     483             : 
     484             : double
     485           0 : Person::getImpatience(const std::string& personID) {
     486           0 :     return getPerson(personID)->getImpatience();
     487             : }
     488             : 
     489             : 
     490             : void
     491          17 : Person::setSpeed(const std::string& personID, double speed) {
     492          17 :     getPerson(personID)->setSpeed(speed);
     493          17 : }
     494             : 
     495             : 
     496             : void
     497          19 : Person::setType(const std::string& personID, const std::string& typeID) {
     498          19 :     MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
     499          19 :     if (vehicleType == nullptr) {
     500           0 :         throw TraCIException("The vehicle type '" + typeID + "' is not known.");
     501             :     }
     502          19 :     getPerson(personID)->replaceVehicleType(vehicleType);
     503          19 : }
     504             : 
     505             : 
     506             : void
     507         270 : Person::add(const std::string& personID, const std::string& edgeID, double pos, double departInSecs, const std::string typeID) {
     508             :     MSTransportable* p;
     509             :     try {
     510         270 :         p = getPerson(personID);
     511         270 :     } catch (TraCIException&) {
     512             :         p = nullptr;
     513         270 :     }
     514             : 
     515           0 :     if (p != nullptr) {
     516           0 :         throw TraCIException("The person " + personID + " to add already exists.");
     517             :     }
     518             : 
     519         270 :     SUMOTime depart = TIME2STEPS(departInSecs);
     520         270 :     SUMOVehicleParameter vehicleParams;
     521             :     vehicleParams.id = personID;
     522             : 
     523         270 :     MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
     524         270 :     if (!vehicleType) {
     525           0 :         throw TraCIException("Invalid type '" + typeID + "' for person '" + personID + "'");
     526             :     }
     527             : 
     528         270 :     const MSEdge* edge = MSEdge::dictionary(edgeID);
     529         270 :     if (!edge) {
     530           0 :         throw TraCIException("Invalid edge '" + edgeID + "' for person: '" + personID + "'");
     531             :     }
     532             : 
     533         270 :     if (departInSecs < 0.) {
     534         186 :         const int proc = (int) - departInSecs;
     535         186 :         if (proc >= static_cast<int>(DepartDefinition::DEF_MAX)) {
     536           0 :             throw TraCIException("Invalid departure time." + toString(depart) + " " + toString(proc));
     537             :         }
     538         186 :         vehicleParams.departProcedure = (DepartDefinition)proc;
     539         186 :         vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
     540          84 :     } else if (depart < MSNet::getInstance()->getCurrentTimeStep()) {
     541          72 :         vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
     542         216 :         WRITE_WARNINGF(TL("Departure time=% for person '%' is in the past; using current time=% instead."),
     543             :                        toString(departInSecs), personID, time2string(vehicleParams.depart));
     544             :     } else {
     545          12 :         vehicleParams.depart = depart;
     546             :     }
     547             : 
     548         270 :     vehicleParams.departPosProcedure = DepartPosDefinition::GIVEN;
     549         270 :     if (fabs(pos) > edge->getLength()) {
     550           0 :         throw TraCIException("Invalid departure position.");
     551             :     }
     552         270 :     if (pos < 0) {
     553          18 :         pos += edge->getLength();
     554             :     }
     555         270 :     vehicleParams.departPos = pos;
     556             : 
     557         270 :     SUMOVehicleParameter* params = new SUMOVehicleParameter(vehicleParams);
     558         270 :     MSTransportable::MSTransportablePlan* plan = new MSTransportable::MSTransportablePlan();
     559         270 :     plan->push_back(new MSStageWaiting(edge, nullptr, 0, depart, pos, "awaiting departure", true));
     560             : 
     561             :     try {
     562         270 :         MSTransportable* person = MSNet::getInstance()->getPersonControl().buildPerson(params, vehicleType, plan, nullptr);
     563         270 :         MSNet::getInstance()->getPersonControl().add(person);
     564           0 :     } catch (ProcessError& e) {
     565           0 :         delete params;
     566           0 :         delete plan;
     567           0 :         throw TraCIException(e.what());
     568           0 :     }
     569         270 : }
     570             : 
     571             : MSStage*
     572          37 : Person::convertTraCIStage(const TraCIStage& stage, const std::string personID) {
     573             :     MSStoppingPlace* bs = nullptr;
     574          37 :     if (!stage.destStop.empty()) {
     575          12 :         bs = MSNet::getInstance()->getStoppingPlace(stage.destStop, SUMO_TAG_BUS_STOP);
     576          12 :         if (bs == nullptr) {
     577           0 :             bs = MSNet::getInstance()->getStoppingPlace(stage.destStop, SUMO_TAG_PARKING_AREA);
     578           0 :             if (bs == nullptr) {
     579           0 :                 throw TraCIException("Invalid stopping place id '" + stage.destStop + "' for person: '" + personID + "'");
     580             :             } else {
     581             :                 // parkingArea is not a proper arrival place
     582             :                 bs = nullptr;
     583             :             }
     584             :         }
     585             :     }
     586          37 :     switch (stage.type) {
     587          12 :         case STAGE_DRIVING: {
     588          12 :             if (stage.edges.empty()) {
     589           0 :                 throw TraCIException("The stage should have at least one edge");
     590             :             }
     591             :             std::string toId = stage.edges.back();
     592          12 :             MSEdge* to = MSEdge::dictionary(toId);
     593          12 :             if (!to) {
     594           0 :                 throw TraCIException("Invalid edge '" + toId + "' for person: '" + personID + "'");
     595             :             }
     596             :             //std::string fromId = stage.edges.front();
     597             :             //MSEdge* from = MSEdge::dictionary(fromId);
     598             :             //if (!from) {
     599             :             //    throw TraCIException("Invalid edge '" + fromId + "' for person: '" + personID + "'");
     600             :             //}
     601          12 :             if (stage.line.empty()) {
     602           0 :                 throw TraCIException("Empty lines parameter for person: '" + personID + "'");
     603             :             }
     604          12 :             double arrivalPos = stage.arrivalPos;
     605          12 :             if (arrivalPos == INVALID_DOUBLE_VALUE) {
     606           6 :                 if (bs != nullptr) {
     607           6 :                     arrivalPos = bs->getEndLanePosition();
     608             :                 } else {
     609             :                     arrivalPos = to->getLength();
     610             :                 }
     611             :             }
     612          24 :             return new MSStageDriving(nullptr, to, bs, arrivalPos, 0.0, StringTokenizer(stage.line).getVector());
     613             :         }
     614             : 
     615          25 :         case STAGE_WALKING: {
     616          25 :             MSTransportable* p = getPerson(personID);
     617             :             ConstMSEdgeVector edges;
     618             :             try {
     619          50 :                 MSEdge::parseEdgesList(stage.edges, edges, "<unknown>");
     620           0 :             } catch (ProcessError& e) {
     621           0 :                 throw TraCIException(e.what());
     622           0 :             }
     623          25 :             if (edges.empty()) {
     624           0 :                 throw TraCIException("Empty edge list for walking stage of person '" + personID + "'.");
     625             :             }
     626          25 :             double arrivalPos = stage.arrivalPos;
     627          25 :             if (fabs(arrivalPos) > edges.back()->getLength()) {
     628           0 :                 throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
     629             :             }
     630          25 :             if (arrivalPos < 0) {
     631           1 :                 arrivalPos += edges.back()->getLength();
     632             :             }
     633          25 :             double speed = p->getMaxSpeed();
     634          50 :             return new MSStageWalking(p->getID(), edges, bs, -1, speed, p->getArrivalPos(), arrivalPos, MSPModel::UNSPECIFIED_POS_LAT);
     635             :         }
     636             : 
     637           0 :         case STAGE_WAITING: {
     638           0 :             MSTransportable* p = getPerson(personID);
     639           0 :             if (stage.travelTime < 0) {
     640           0 :                 throw TraCIException("Duration for person: '" + personID + "' must not be negative");
     641             :             }
     642           0 :             return new MSStageWaiting(p->getArrivalEdge(), nullptr, TIME2STEPS(stage.travelTime), 0, p->getArrivalPos(), stage.description, false);
     643             :         }
     644             :         default:
     645             :             return nullptr;
     646             :     }
     647             : }
     648             : 
     649             : 
     650             : void
     651          25 : Person::appendStage(const std::string& personID, const TraCIStage& stage) {
     652          25 :     MSTransportable* p = getPerson(personID);
     653          25 :     MSStage* personStage = convertTraCIStage(stage, personID);
     654          25 :     p->appendStage(personStage);
     655          25 : }
     656             : 
     657             : 
     658             : void
     659          12 : Person::replaceStage(const std::string& personID, const int stageIndex, const TraCIStage& stage) {
     660          12 :     MSTransportable* p = getPerson(personID);
     661          12 :     if (stageIndex >= p->getNumRemainingStages()) {
     662           0 :         throw TraCIException("Specified stage index:  is not valid for person " + personID);
     663             :     }
     664          12 :     MSStage* personStage = convertTraCIStage(stage, personID);
     665             :     // removing the current stage triggers abort+proceed so the replacement
     666             :     // stage must be ready beforehand
     667          12 :     p->appendStage(personStage, stageIndex + 1);
     668          12 :     p->removeStage(stageIndex);
     669          12 : }
     670             : 
     671             : 
     672             : void
     673          19 : Person::appendDrivingStage(const std::string& personID, const std::string& toEdge, const std::string& lines, const std::string& stopID) {
     674          19 :     MSTransportable* p = getPerson(personID);
     675          19 :     const MSEdge* edge = MSEdge::dictionary(toEdge);
     676          19 :     if (!edge) {
     677           0 :         throw TraCIException("Invalid edge '" + toEdge + "' for person: '" + personID + "'");
     678             :     }
     679          19 :     if (lines.size() == 0) {
     680           0 :         throw TraCIException("Empty lines parameter for person: '" + personID + "'");
     681             :     }
     682             :     MSStoppingPlace* bs = nullptr;
     683          19 :     if (stopID != "") {
     684           0 :         bs = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
     685           0 :         if (bs == nullptr) {
     686           0 :             throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
     687             :         }
     688             :     }
     689          38 :     p->appendStage(new MSStageDriving(nullptr, edge, bs, edge->getLength() - NUMERICAL_EPS, 0.0, StringTokenizer(lines).getVector()));
     690          19 : }
     691             : 
     692             : 
     693             : void
     694          31 : Person::appendWaitingStage(const std::string& personID, double duration, const std::string& description, const std::string& stopID) {
     695          31 :     MSTransportable* p = getPerson(personID);
     696          31 :     if (duration < 0) {
     697           0 :         throw TraCIException("Duration for person: '" + personID + "' must not be negative");
     698             :     }
     699             :     MSStoppingPlace* bs = nullptr;
     700          31 :     if (stopID != "") {
     701          12 :         bs = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
     702          12 :         if (bs == nullptr) {
     703           0 :             throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
     704             :         }
     705             :     }
     706          62 :     p->appendStage(new MSStageWaiting(p->getArrivalEdge(), nullptr, TIME2STEPS(duration), 0, p->getArrivalPos(), description, false));
     707          31 : }
     708             : 
     709             : 
     710             : void
     711         259 : Person::appendWalkingStage(const std::string& personID, const std::vector<std::string>& edgeIDs, double arrivalPos, double duration, double speed, const std::string& stopID) {
     712         259 :     MSTransportable* p = getPerson(personID);
     713             :     ConstMSEdgeVector edges;
     714             :     try {
     715         518 :         MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
     716           0 :     } catch (ProcessError& e) {
     717           0 :         throw TraCIException(e.what());
     718           0 :     }
     719         259 :     if (edges.empty()) {
     720           0 :         throw TraCIException("Empty edge list for walking stage of person '" + personID + "'.");
     721             :     }
     722         259 :     if (fabs(arrivalPos) > edges.back()->getLength()) {
     723           0 :         throw TraCIException("Invalid arrivalPos for walking stage of person '" + personID + "'.");
     724             :     }
     725         259 :     if (arrivalPos < 0) {
     726          31 :         arrivalPos += edges.back()->getLength();
     727             :     }
     728         259 :     if (speed < 0) {
     729         259 :         speed = p->getMaxSpeed();
     730             :     }
     731             :     MSStoppingPlace* bs = nullptr;
     732         259 :     if (stopID != "") {
     733           0 :         bs = MSNet::getInstance()->getStoppingPlace(stopID, SUMO_TAG_BUS_STOP);
     734           0 :         if (bs == nullptr) {
     735           0 :             throw TraCIException("Invalid stopping place id '" + stopID + "' for person: '" + personID + "'");
     736             :         }
     737             :     }
     738         777 :     p->appendStage(new MSStageWalking(p->getID(), edges, bs, TIME2STEPS(duration), speed, p->getArrivalPos(), arrivalPos, MSPModel::UNSPECIFIED_POS_LAT));
     739         259 : }
     740             : 
     741             : 
     742             : void
     743         203 : Person::removeStage(const std::string& personID, int nextStageIndex) {
     744         203 :     MSTransportable* p = getPerson(personID);
     745         202 :     if (nextStageIndex >= p->getNumRemainingStages()) {
     746           0 :         throw TraCIException("The stage index must be lower than the number of remaining stages.");
     747             :     }
     748         202 :     if (nextStageIndex < 0) {
     749           0 :         throw TraCIException("The stage index may not be negative.");
     750             :     }
     751         202 :     p->removeStage(nextStageIndex);
     752         202 : }
     753             : 
     754             : 
     755             : void
     756        1189 : Person::rerouteTraveltime(const std::string& personID) {
     757        1189 :     MSPerson* p = getPerson(personID);
     758        1189 :     if (p->getNumRemainingStages() == 0) {
     759           0 :         throw TraCIException("Person '" + personID + "' has no remaining stages.");
     760             :     }
     761        1189 :     const MSEdge* from = p->getEdge();
     762        1189 :     double  departPos = p->getEdgePos();
     763             :     // reroute to the start of the next-non-walking stage
     764             :     int firstIndex;
     765        1189 :     if (p->getCurrentStageType() == MSStageType::WALKING) {
     766             :         firstIndex = 0;
     767           6 :     } else if (p->getCurrentStageType() == MSStageType::WAITING) {
     768           6 :         if (p->getNumRemainingStages() < 2 || p->getStageType(1) != MSStageType::WALKING) {
     769           0 :             throw TraCIException("Person '" + personID + "' cannot reroute after the current stop.");
     770             :         }
     771             :         firstIndex = 1;
     772             :     } else {
     773           0 :         throw TraCIException("Person '" + personID + "' cannot reroute in stage type '" + toString((int)p->getCurrentStageType()) + "'.");
     774             :     }
     775        1189 :     int nextIndex = firstIndex + 1;
     776        1195 :     for (; nextIndex < p->getNumRemainingStages(); nextIndex++) {
     777          24 :         if (p->getStageType(nextIndex) != MSStageType::WALKING) {
     778             :             break;
     779             :         }
     780             :     }
     781        1189 :     MSStage* destStage = p->getNextStage(nextIndex - 1);
     782        1189 :     const MSEdge* to = destStage->getEdges().back();
     783        1189 :     double arrivalPos = destStage->getArrivalPos();
     784        1189 :     double speed = p->getMaxSpeed();
     785             :     ConstMSEdgeVector newEdges;
     786        2378 :     MSNet::getInstance()->getPedestrianRouter(0).compute(from, to, departPos, arrivalPos, speed, 0, nullptr, newEdges);
     787        1189 :     if (newEdges.empty()) {
     788           0 :         throw TraCIException("Could not find new route for person '" + personID + "'.");
     789             :     }
     790        1189 :     ConstMSEdgeVector oldEdges = p->getNextStage(firstIndex)->getEdges();
     791             :     assert(!oldEdges.empty());
     792        1189 :     if (oldEdges.front()->getFunction() != SumoXMLEdgeFunc::NORMAL) {
     793             :         oldEdges.erase(oldEdges.begin());
     794             :     }
     795             :     //std::cout << " remainingStages=" << p->getNumRemainingStages() << " oldEdges=" << toString(oldEdges) << " newEdges=" << toString(newEdges) << " firstIndex=" << firstIndex << " nextIndex=" << nextIndex << "\n";
     796        1189 :     if (newEdges == oldEdges && (firstIndex + 1 == nextIndex)) {
     797             :         return;
     798             :     }
     799          44 :     if (newEdges.front() != from) {
     800             :         // @note: maybe this should be done automatically by the router
     801           5 :         newEdges.insert(newEdges.begin(), from);
     802             :     }
     803          44 :     p->reroute(newEdges, departPos, firstIndex, nextIndex);
     804             : }
     805             : 
     806             : 
     807             : void
     808          20 : Person::moveTo(const std::string& personID, const std::string& laneID, double pos, double posLat) {
     809          20 :     MSPerson* p = getPerson(personID);
     810          20 :     MSLane* l = MSLane::dictionary(laneID);
     811          20 :     if (l == nullptr) {
     812           0 :         throw TraCIException("Unknown lane '" + laneID + "'.");
     813             :     }
     814          20 :     if (posLat == INVALID_DOUBLE_VALUE) {
     815          20 :         posLat = 0;
     816           0 :     } else if (fabs(posLat) >= (0.5 * (l->getWidth() + p->getVehicleType().getWidth()) + MSPModel::SIDEWALK_OFFSET)) {
     817             :         // see MSPModel_Striping::moveToXY
     818           0 :         throw TraCIException("Invalid lateral position " + toString(posLat) + " on lane '" + laneID + "'.");
     819             :     }
     820          20 :     switch (p->getStageType(0)) {
     821             :         case MSStageType::WALKING: {
     822          20 :             MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
     823             :             assert(s != 0);
     824          20 :             s->getPState()->moveTo(p, l, pos, posLat, SIMSTEP);
     825             :             break;
     826             :         }
     827           0 :         default:
     828           0 :             throw TraCIException("Command moveTo is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + ".");
     829             :     }
     830          20 : }
     831             : 
     832             : 
     833             : void
     834       16345 : Person::moveToXY(const std::string& personID, const std::string& edgeID, const double x, const double y, double angle, const int keepRoute, double matchThreshold) {
     835       16345 :     MSPerson* p = getPerson(personID);
     836       16345 :     const bool doKeepRoute = (keepRoute & 1) != 0;
     837       16345 :     const bool mayLeaveNetwork = (keepRoute & 2) != 0;
     838       16345 :     const bool ignorePermissions = (keepRoute & 4) != 0;
     839       16345 :     SUMOVehicleClass vClass = ignorePermissions ? SVC_IGNORING : p->getVClass();
     840             :     Position pos(x, y);
     841             : #ifdef DEBUG_MOVEXY
     842             :     const double origAngle = angle;
     843             : #endif
     844             :     // angle must be in [0,360] because it will be compared against those returned by naviDegree()
     845             :     // angle set to INVALID_DOUBLE_VALUE is ignored in the evaluated and later set to the angle of the matched lane
     846       16345 :     if (angle != INVALID_DOUBLE_VALUE) {
     847       13492 :         while (angle >= 360.) {
     848           0 :             angle -= 360.;
     849             :         }
     850       13492 :         while (angle < 0.) {
     851           0 :             angle += 360.;
     852             :         }
     853             :     }
     854       16345 :     Position currentPos = p->getPosition();
     855             : #ifdef DEBUG_MOVEXY
     856             :     std::cout << std::endl << "begin person " << p->getID() << " lanePos:" << p->getEdgePos() << " edge:" << Named::getIDSecure(p->getEdge()) << "\n";
     857             :     std::cout << " want pos:" << pos << " edgeID:" << edgeID <<  " origAngle:" << origAngle << " angle:" << angle << " keepRoute:" << keepRoute << std::endl;
     858             : #endif
     859             : 
     860             :     ConstMSEdgeVector edges;
     861       16345 :     MSLane* lane = nullptr;
     862             :     double lanePos;
     863             :     double lanePosLat = 0;
     864       16345 :     double bestDistance = std::numeric_limits<double>::max();
     865       16345 :     int routeOffset = 0;
     866             :     bool found = false;
     867       16345 :     double maxRouteDistance = matchThreshold;
     868             : 
     869             :     ConstMSEdgeVector ev;
     870       16351 :     ev.push_back(p->getEdge());
     871             :     int routeIndex = 0;
     872       16345 :     MSLane* currentLane = const_cast<MSLane*>(getSidewalk<MSEdge, MSLane>(p->getEdge()));
     873       16345 :     switch (p->getStageType(0)) {
     874             :         case MSStageType::WALKING: {
     875       16324 :             MSStageWalking* s = dynamic_cast<MSStageWalking*>(p->getCurrentStage());
     876             :             assert(s != 0);
     877       32648 :             ev = s->getEdges();
     878       16324 :             routeIndex = (int)(s->getRouteStep() - s->getRoute().begin());
     879             :         }
     880       16324 :         break;
     881             :         default:
     882             :             break;
     883             :     }
     884       16345 :     if (doKeepRoute) {
     885             :         // case a): vehicle is on its earlier route
     886             :         //  we additionally assume it is moving forward (SUMO-limit);
     887             :         //  note that the route ("edges") is not changed in this case
     888       13887 :         found = Helper::moveToXYMap_matchingRoutePosition(pos, edgeID,
     889             :                 ev, routeIndex, vClass, true,
     890             :                 bestDistance, &lane, lanePos, routeOffset);
     891             :     } else {
     892        2458 :         double speed = pos.distanceTo2D(p->getPosition()); // !!!veh->getSpeed();
     893        2458 :         found = Helper::moveToXYMap(pos, maxRouteDistance, mayLeaveNetwork, edgeID, angle,
     894        2458 :                                     speed, ev, routeIndex, currentLane, p->getEdgePos(), currentLane != nullptr,
     895             :                                     vClass, true,
     896             :                                     bestDistance, &lane, lanePos, routeOffset, edges);
     897        2458 :         if (edges.size() != 0 && ev.size() > 1) {
     898             :             // try to rebuild the route
     899          54 :             const MSEdge* origEdge = p->getEdge();
     900             :             assert(lane != nullptr);
     901             :             const MSJunction* originalTarget = nullptr;
     902          54 :             if (origEdge->isNormal()) {
     903          29 :                 if (routeIndex == 0) {
     904          29 :                     if (origEdge->getToJunction() == ev[1]->getToJunction() || origEdge->getToJunction() == ev[1]->getFromJunction()) {
     905             :                         originalTarget = origEdge->getToJunction();
     906             :                     } else {
     907             :                         originalTarget = origEdge->getFromJunction();
     908             :                     }
     909             :                 } else {
     910           0 :                     if (origEdge->getToJunction() == ev[routeIndex - 1]->getToJunction() || origEdge->getToJunction() == ev[routeIndex - 1]->getFromJunction()) {
     911             :                         originalTarget = origEdge->getFromJunction();
     912             :                     } else {
     913             :                         originalTarget = origEdge->getToJunction();
     914             :                     }
     915             :                 }
     916             :             } else {
     917             :                 originalTarget = origEdge->getToJunction();
     918             :                 assert(originalTarget == origEdge->getFromJunction());
     919             :             }
     920          54 :             const MSEdge* newEdge = edges[0];
     921          54 :             if (edges[0]->getFromJunction() == originalTarget || edges[0]->getToJunction() == originalTarget) {
     922          48 :                 edges = ev;
     923          48 :                 edges[routeIndex] = newEdge;
     924             :             }
     925             :         }
     926             :     }
     927       16345 :     if ((found && bestDistance <= maxRouteDistance) || mayLeaveNetwork) {
     928             :         // compute lateral offset
     929       16339 :         if (found) {
     930       16339 :             const double perpDist = lane->getShape().distance2D(pos, false);
     931       16339 :             if (perpDist != GeomHelper::INVALID_OFFSET) {
     932             :                 lanePosLat = perpDist;
     933       16339 :                 if (!mayLeaveNetwork) {
     934        1961 :                     lanePosLat = MIN2(lanePosLat, 0.5 * (lane->getWidth() + p->getVehicleType().getWidth()));
     935             :                 }
     936             :                 // figure out whether the offset is to the left or to the right
     937       16339 :                 PositionVector tmp = lane->getShape();
     938             :                 try {
     939       16339 :                     tmp.move2side(-lanePosLat); // moved to left
     940           0 :                 } catch (ProcessError&) {
     941           0 :                     WRITE_WARNINGF(TL("Could not determine position on lane '%' at lateral position %."), lane->getID(), toString(-lanePosLat));
     942           0 :                 }
     943             :                 //std::cout << " lane=" << lane->getID() << " posLat=" << lanePosLat << " shape=" << lane->getShape() << " tmp=" << tmp << " tmpDist=" << tmp.distance2D(pos) << "\n";
     944       16339 :                 if (tmp.distance2D(pos) > perpDist) {
     945             :                     lanePosLat = -lanePosLat;
     946             :                 }
     947       16339 :             }
     948             :         }
     949       16339 :         if (found && !mayLeaveNetwork && MSGlobals::gLateralResolution < 0) {
     950             :             // mapped position may differ from pos
     951        1961 :             pos = lane->geometryPositionAtOffset(lanePos, -lanePosLat);
     952             :         }
     953             :         assert((found && lane != 0) || (!found && lane == 0));
     954       16339 :         switch (p->getStageType(0)) {
     955       16318 :             case MSStageType::WALKING: {
     956       16318 :                 if (angle == INVALID_DOUBLE_VALUE) {
     957             :                     // walking angle cannot be deduced from road angle so we always use the last pos
     958        2826 :                     angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
     959             :                 }
     960             :                 break;
     961             :             }
     962          21 :             case MSStageType::WAITING_FOR_DEPART:
     963             :             case MSStageType::WAITING: {
     964          21 :                 if (p->getNumRemainingStages() <= 1 || p->getStageType(1) != MSStageType::WALKING) {
     965             :                     // insert walking stage after the current stage
     966           5 :                     ConstMSEdgeVector route({p->getEdge()});
     967           5 :                     const double departPos = p->getCurrentStage()->getArrivalPos();
     968          10 :                     p->appendStage(new MSStageWalking(p->getID(), route, nullptr, -1, -1, departPos, departPos, MSPModel::UNSPECIFIED_POS_LAT), 1);
     969             :                 }
     970             :                 // abort waiting stage and proceed to walking stage
     971          21 :                 p->removeStage(0);
     972             :                 assert(p->getStageType(0) == MSStageType::WALKING);
     973          21 :                 if (angle == INVALID_DOUBLE_VALUE) {
     974          21 :                     if (lane != nullptr && !lane->getEdge().isWalkingArea()) {
     975          21 :                         angle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(lanePos));
     976             :                     } else {
     977             :                         // compute angle outside road network or on walkingarea from old and new position
     978           0 :                         angle = GeomHelper::naviDegree(p->getPosition().angleTo2D(pos));
     979             :                     }
     980             :                 }
     981             :                 break;
     982             :             }
     983           0 :             default:
     984           0 :                 throw TraCIException("Command moveToXY is not supported for person '" + personID + "' while " + p->getCurrentStageDescription() + ".");
     985             :         }
     986       16429 :         Helper::setRemoteControlled(p, pos, lane, lanePos, lanePosLat, angle, routeOffset, edges, MSNet::getInstance()->getCurrentTimeStep());
     987             :     } else {
     988           6 :         if (lane == nullptr) {
     989           0 :             throw TraCIException("Could not map person '" + personID + "' no road found within " + toString(maxRouteDistance) + "m.");
     990             :         } else {
     991          12 :             throw TraCIException("Could not map person '" + personID + "' distance to road is " + toString(bestDistance) + ".");
     992             :         }
     993             :     }
     994       16339 : }
     995             : 
     996             : 
     997             : /** untested setter functions which alter the person's vtype ***/
     998             : 
     999             : void
    1000          77 : Person::setParameter(const std::string& personID, const std::string& key, const std::string& value) {
    1001          77 :     MSTransportable* p = getPerson(personID);
    1002         154 :     if (StringUtils::startsWith(key, "device.")) {
    1003           0 :         throw TraCIException("Person '" + personID + "' does not support device parameters\n");
    1004         154 :     } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
    1005           0 :         throw TraCIException("Person '" + personID + "' does not support laneChangeModel parameters\n");
    1006         154 :     } else if (StringUtils::startsWith(key, "carFollowModel.")) {
    1007           0 :         throw TraCIException("Person '" + personID + "' does not support carFollowModel parameters\n");
    1008         154 :     } else if (StringUtils::startsWith(key, "junctionModel.")) {
    1009             :         try {
    1010             :             // use the whole key (including junctionModel prefix)
    1011          12 :             p->setJunctionModelParameter(key, value);
    1012           6 :         } catch (InvalidArgument& e) {
    1013             :             // error message includes id since it is also used for xml input
    1014          12 :             throw TraCIException(e.what());
    1015           6 :         }
    1016          65 :     } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
    1017           0 :         throw TraCIException("Person '" + personID + "' does not support chanigng device status\n");
    1018             :     } else {
    1019          65 :         ((SUMOVehicleParameter&)p->getParameter()).setParameter(key, value);
    1020             :     }
    1021          71 : }
    1022             : 
    1023             : 
    1024             : void
    1025           2 : Person::setLength(const std::string& personID, double length) {
    1026           2 :     getPerson(personID)->getSingularType().setLength(length);
    1027           2 : }
    1028             : 
    1029             : 
    1030             : void
    1031           0 : Person::setMaxSpeed(const std::string& personID, double speed) {
    1032           0 :     getPerson(personID)->getSingularType().setMaxSpeed(speed);
    1033           0 : }
    1034             : 
    1035             : 
    1036             : void
    1037           0 : Person::setVehicleClass(const std::string& personID, const std::string& clazz) {
    1038           0 :     getPerson(personID)->getSingularType().setVClass(getVehicleClassID(clazz));
    1039           0 : }
    1040             : 
    1041             : 
    1042             : void
    1043           0 : Person::setShapeClass(const std::string& personID, const std::string& clazz) {
    1044           0 :     getPerson(personID)->getSingularType().setShape(getVehicleShapeID(clazz));
    1045           0 : }
    1046             : 
    1047             : 
    1048             : void
    1049           0 : Person::setEmissionClass(const std::string& personID, const std::string& clazz) {
    1050           0 :     getPerson(personID)->getSingularType().setEmissionClass(PollutantsInterface::getClassByName(clazz));
    1051           0 : }
    1052             : 
    1053             : 
    1054             : void
    1055           2 : Person::setWidth(const std::string& personID, double width) {
    1056           2 :     getPerson(personID)->getSingularType().setWidth(width);
    1057           2 : }
    1058             : 
    1059             : 
    1060             : void
    1061           2 : Person::setHeight(const std::string& personID, double height) {
    1062           2 :     getPerson(personID)->getSingularType().setHeight(height);
    1063           2 : }
    1064             : 
    1065             : 
    1066             : void
    1067           2 : Person::setMinGap(const std::string& personID, double minGap) {
    1068           2 :     getPerson(personID)->getSingularType().setMinGap(minGap);
    1069           2 : }
    1070             : 
    1071             : 
    1072             : void
    1073           0 : Person::setAccel(const std::string& personID, double accel) {
    1074           0 :     getPerson(personID)->getSingularType().setAccel(accel);
    1075           0 : }
    1076             : 
    1077             : 
    1078             : void
    1079           0 : Person::setDecel(const std::string& personID, double decel) {
    1080           0 :     getPerson(personID)->getSingularType().setDecel(decel);
    1081           0 : }
    1082             : 
    1083             : 
    1084             : void
    1085           0 : Person::setEmergencyDecel(const std::string& personID, double decel) {
    1086           0 :     getPerson(personID)->getSingularType().setEmergencyDecel(decel);
    1087           0 : }
    1088             : 
    1089             : 
    1090             : void
    1091           0 : Person::setApparentDecel(const std::string& personID, double decel) {
    1092           0 :     getPerson(personID)->getSingularType().setApparentDecel(decel);
    1093           0 : }
    1094             : 
    1095             : 
    1096             : void
    1097           0 : Person::setImperfection(const std::string& personID, double imperfection) {
    1098           0 :     getPerson(personID)->getSingularType().setImperfection(imperfection);
    1099           0 : }
    1100             : 
    1101             : 
    1102             : void
    1103           0 : Person::setBoardingDuration(const std::string& personID, double boardingDuration)  {
    1104           0 :     Helper::getPerson(personID)->getSingularType().setBoardingDuration(TIME2STEPS(boardingDuration));
    1105           0 : }
    1106             : 
    1107             : 
    1108             : void
    1109           0 : Person::setImpatience(const std::string& personID, double impatience)  {
    1110           0 :     Helper::getVehicle(personID)->getSingularType().setImpatience(impatience);
    1111           0 : }
    1112             : 
    1113             : 
    1114             : 
    1115             : void
    1116           0 : Person::setTau(const std::string& personID, double tau) {
    1117           0 :     getPerson(personID)->getSingularType().setTau(tau);
    1118           0 : }
    1119             : 
    1120             : 
    1121             : void
    1122           0 : Person::setMinGapLat(const std::string& personID, double minGapLat) {
    1123           0 :     getPerson(personID)->getSingularType().setMinGapLat(minGapLat);
    1124           0 : }
    1125             : 
    1126             : 
    1127             : void
    1128           0 : Person::setMaxSpeedLat(const std::string& personID, double speed) {
    1129           0 :     getPerson(personID)->getSingularType().setMaxSpeedLat(speed);
    1130           0 : }
    1131             : 
    1132             : 
    1133             : void
    1134           0 : Person::setLateralAlignment(const std::string& personID, const std::string& latAlignment) {
    1135             :     double lao;
    1136             :     LatAlignmentDefinition lad;
    1137           0 :     if (SUMOVTypeParameter::parseLatAlignment(latAlignment, lao, lad)) {
    1138           0 :         getPerson(personID)->getSingularType().setPreferredLateralAlignment(lad, lao);
    1139             :     } else {
    1140           0 :         throw TraCIException("Unknown value '" + latAlignment + "' when setting latAlignment for person '" + personID + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
    1141             :     }
    1142           0 : }
    1143             : 
    1144             : 
    1145             : void
    1146          12 : Person::setSpeedFactor(const std::string& personID, double factor) {
    1147          12 :     getPerson(personID)->setChosenSpeedFactor(factor);
    1148          12 : }
    1149             : 
    1150             : 
    1151             : void
    1152           0 : Person::setActionStepLength(const std::string& personID, double actionStepLength, bool resetActionOffset) {
    1153           0 :     getPerson(personID)->getSingularType().setActionStepLength(SUMOVehicleParserHelper::processActionStepLength(actionStepLength), resetActionOffset);
    1154           0 : }
    1155             : 
    1156             : void
    1157          10 : Person::remove(const std::string& personID, char /*reason*/) {
    1158          10 :     MSPerson* person = getPerson(personID);
    1159             :     // remove all stages after the current and then abort the current stage
    1160             :     // (without adding a zero-length waiting stage)
    1161          20 :     while (person->getNumRemainingStages() > 1) {
    1162          10 :         person->removeStage(1);
    1163             :     }
    1164          10 :     person->removeStage(0, false);
    1165          10 : }
    1166             : 
    1167             : void
    1168           7 : Person::setColor(const std::string& personID, const TraCIColor& c) {
    1169           7 :     const SUMOVehicleParameter& p = getPerson(personID)->getParameter();
    1170           7 :     p.color.set((unsigned char)c.r, (unsigned char)c.g, (unsigned char)c.b, (unsigned char)c.a);
    1171           7 :     p.parametersSet |= VEHPARS_COLOR_SET;
    1172           7 : }
    1173             : 
    1174             : 
    1175        8229 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Person, PERSON)
    1176             : 
    1177             : 
    1178             : MSPerson*
    1179      206667 : Person::getPerson(const std::string& personID) {
    1180      206667 :     return Helper::getPerson(personID);
    1181             : }
    1182             : 
    1183             : 
    1184             : void
    1185       20219 : Person::storeShape(const std::string& id, PositionVector& shape) {
    1186       20219 :     shape.push_back(getPerson(id)->getPosition());
    1187       20219 : }
    1188             : 
    1189             : 
    1190             : std::shared_ptr<VariableWrapper>
    1191         267 : Person::makeWrapper() {
    1192         267 :     return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
    1193             : }
    1194             : 
    1195             : 
    1196             : bool
    1197      164621 : Person::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
    1198      164621 :     switch (variable) {
    1199       44579 :         case TRACI_ID_LIST:
    1200       44579 :             return wrapper->wrapStringList(objID, variable, getIDList());
    1201          18 :         case ID_COUNT:
    1202          18 :             return wrapper->wrapInt(objID, variable, getIDCount());
    1203      109254 :         case VAR_POSITION:
    1204      109254 :             return wrapper->wrapPosition(objID, variable, getPosition(objID));
    1205          11 :         case VAR_POSITION3D:
    1206          11 :             return wrapper->wrapPosition(objID, variable, getPosition(objID, true));
    1207          91 :         case VAR_ANGLE:
    1208          91 :             return wrapper->wrapDouble(objID, variable, getAngle(objID));
    1209           9 :         case VAR_SLOPE:
    1210           9 :             return wrapper->wrapDouble(objID, variable, getSlope(objID));
    1211          29 :         case VAR_SPEED:
    1212          29 :             return wrapper->wrapDouble(objID, variable, getSpeed(objID));
    1213         991 :         case VAR_ROAD_ID:
    1214        1982 :             return wrapper->wrapString(objID, variable, getRoadID(objID));
    1215         245 :         case VAR_LANE_ID:
    1216         490 :             return wrapper->wrapString(objID, variable, getLaneID(objID));
    1217          95 :         case VAR_LANEPOSITION:
    1218          95 :             return wrapper->wrapDouble(objID, variable, getLanePosition(objID));
    1219          11 :         case VAR_COLOR:
    1220          11 :             return wrapper->wrapColor(objID, variable, getColor(objID));
    1221        1194 :         case VAR_WAITING_TIME:
    1222        1194 :             return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
    1223           0 :         case VAR_IMPATIENCE:
    1224           0 :             return wrapper->wrapDouble(objID, variable, getImpatience(objID));
    1225          23 :         case VAR_TYPE:
    1226          46 :             return wrapper->wrapString(objID, variable, getTypeID(objID));
    1227           8 :         case VAR_SPEED_FACTOR:
    1228           8 :             return wrapper->wrapDouble(objID, variable, getSpeedFactor(objID));
    1229         143 :         case VAR_NEXT_EDGE:
    1230         286 :             return wrapper->wrapString(objID, variable, getNextEdge(objID));
    1231         190 :         case VAR_STAGES_REMAINING:
    1232         190 :             return wrapper->wrapInt(objID, variable, getRemainingStages(objID));
    1233           9 :         case VAR_VEHICLE:
    1234          18 :             return wrapper->wrapString(objID, variable, getVehicle(objID));
    1235           8 :         case VAR_MAXSPEED:
    1236             :             // integrate desiredMaxSpeed and individual speedFactor
    1237           8 :             return wrapper->wrapDouble(objID, variable, getMaxSpeed(objID));
    1238         846 :         case libsumo::VAR_PARAMETER:
    1239         846 :             paramData->readUnsignedByte();
    1240        1692 :             return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
    1241          24 :         case libsumo::VAR_PARAMETER_WITH_KEY:
    1242          24 :             paramData->readUnsignedByte();
    1243          24 :             return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
    1244             :         case VAR_TAXI_RESERVATIONS:
    1245             :             // we cannot use the general fall through here because we do not have an object id
    1246             :             return false;
    1247        2145 :         default:
    1248        4286 :             return libsumo::VehicleType::handleVariable(getTypeID(objID), variable, wrapper, paramData);
    1249             :     }
    1250             : }
    1251             : 
    1252             : 
    1253             : }
    1254             : 
    1255             : 
    1256             : /****************************************************************************/

Generated by: LCOV version 1.14