LCOV - code coverage report
Current view: top level - src/utils/vehicle - SUMORouteHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 94.6 % 331 313
Test Date: 2024-11-23 15:47:30 Functions: 84.6 % 13 11

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-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    SUMORouteHandler.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Sascha Krieg
      18              : /// @author  Michael Behrisch
      19              : /// @date    Mon, 9 Jul 2001
      20              : ///
      21              : // Parser for routes during their loading
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/options/OptionsCont.h>
      27              : #include <utils/vehicle/SUMOVTypeParameter.h>
      28              : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      29              : #include <utils/xml/XMLSubSys.h>
      30              : 
      31              : #include "SUMORouteHandler.h"
      32              : 
      33              : 
      34              : // ===========================================================================
      35              : // method definitions
      36              : // ===========================================================================
      37              : 
      38        95349 : SUMORouteHandler::SUMORouteHandler(const std::string& file, const std::string& expectedRoot, const bool hardFail) :
      39              :     SUMOSAXHandler(file, expectedRoot),
      40        95349 :     myHardFail(hardFail),
      41        95349 :     myVehicleParameter(nullptr),
      42        95349 :     myLastDepart(-1),
      43        95349 :     myActiveRouteColor(nullptr),
      44        95349 :     myCurrentCosts(0.),
      45        95349 :     myCurrentVType(nullptr),
      46        95349 :     myBeginDefault(string2time(OptionsCont::getOptions().getString("begin"))),
      47        95349 :     myEndDefault(string2time(OptionsCont::getOptions().getString("end"))),
      48        95349 :     myFirstDepart(-1),
      49        95349 :     myInsertStopEdgesAt(-1),
      50        95349 :     myAllowInternalRoutes(false) {
      51        95349 : }
      52              : 
      53              : 
      54        92425 : SUMORouteHandler::~SUMORouteHandler() {
      55        92425 :     delete myVehicleParameter;
      56        92425 :     delete myCurrentVType;
      57        92425 : }
      58              : 
      59              : 
      60              : bool
      61       442614 : SUMORouteHandler::checkLastDepart() {
      62       442614 :     if (myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
      63       441738 :         if (myVehicleParameter->depart < myLastDepart) {
      64            2 :             WRITE_WARNINGF(TL("Route file should be sorted by departure time, ignoring '%'!"), myVehicleParameter->id);
      65            1 :             return false;
      66              :         }
      67              :     }
      68              :     return true;
      69              : }
      70              : 
      71              : 
      72              : void
      73       489460 : SUMORouteHandler::registerLastDepart() {
      74              :     // register only non public transport to parse all public transport lines in advance
      75       489460 :     if (myVehicleParameter && myVehicleParameter->line == "" && myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
      76       484369 :         myLastDepart = myVehicleParameter->depart;
      77       484369 :         if (myFirstDepart == -1) {
      78        43214 :             myFirstDepart = myLastDepart;
      79              :         }
      80              :     }
      81              :     // else: we don't know when this vehicle will depart. keep the previous known depart time
      82       489460 : }
      83              : 
      84              : 
      85              : void
      86     11265620 : SUMORouteHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
      87     11265620 :     myElementStack.push_back(element);
      88     11265620 :     switch (element) {
      89       395884 :         case SUMO_TAG_VEHICLE:
      90              :         case SUMO_TAG_PERSON:
      91              :         case SUMO_TAG_CONTAINER:
      92              :             // if myVehicleParameter is nullptr this will do nothing
      93       395884 :             delete myVehicleParameter;
      94              :             // we set to nullptr to have a consistent state if the parsing fails
      95       395884 :             myVehicleParameter = nullptr;
      96       395884 :             myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
      97       395624 :             myParamStack.push_back(myVehicleParameter);
      98       395624 :             if (element != SUMO_TAG_VEHICLE) {
      99        42183 :                 addTransportable(attrs, element == SUMO_TAG_PERSON);
     100              :             }
     101              :             break;
     102        22426 :         case SUMO_TAG_FLOW:
     103              :             // delete if myVehicleParameter isn't null
     104        22426 :             if (myVehicleParameter) {
     105            0 :                 delete myVehicleParameter;
     106            0 :                 myVehicleParameter = nullptr;
     107              :             }
     108              :             // parse vehicle parameters
     109              :             // might be called to parse vehicles from additional file in the
     110              :             // context of quickReload. In this case, rerouter flows must be ignored
     111        22426 :             if (myElementStack.size() == 1 || myElementStack[myElementStack.size() - 2] != SUMO_TAG_CALIBRATOR) {
     112        22426 :                 myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOW, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
     113              :             }
     114              :             // check if myVehicleParameter was successfully created
     115        22308 :             if (myVehicleParameter) {
     116              :                 // check tag
     117        22308 :                 if (myVehicleParameter->routeid.empty()) {
     118              :                     // open a route flow (It could be a flow with embedded route)
     119        12434 :                     openFlow(attrs);
     120              :                 } else {
     121              :                     // open a route flow
     122         9874 :                     openRouteFlow(attrs);
     123              :                 }
     124        22308 :                 myParamStack.push_back(myVehicleParameter);
     125              :             }
     126              :             break;
     127         1979 :         case SUMO_TAG_PERSONFLOW:
     128              :         case SUMO_TAG_CONTAINERFLOW:
     129              :             // delete if myVehicleParameter isn't null
     130         1979 :             if (myVehicleParameter) {
     131            0 :                 delete myVehicleParameter;
     132            0 :                 myVehicleParameter = nullptr;
     133              :             }
     134              :             // create a new flow
     135         1979 :             myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes((SumoXMLTag)element, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
     136         1979 :             myParamStack.push_back(myVehicleParameter);
     137         1979 :             break;
     138        60383 :         case SUMO_TAG_VTYPE:
     139              :             // delete if myCurrentVType isn't null
     140        60383 :             if (myCurrentVType != nullptr) {
     141            4 :                 delete myCurrentVType;
     142            4 :                 myCurrentVType = nullptr;
     143              :             }
     144              :             // create a new vType
     145        60383 :             myCurrentVType = SUMOVehicleParserHelper::beginVTypeParsing(attrs, myHardFail, getFileName());
     146        60353 :             myParamStack.push_back(myCurrentVType);
     147        60353 :             break;
     148          520 :         case SUMO_TAG_VTYPE_DISTRIBUTION:
     149          520 :             openVehicleTypeDistribution(attrs);
     150          520 :             break;
     151       395929 :         case SUMO_TAG_ROUTE:
     152       395929 :             openRoute(attrs);
     153       395861 :             break;
     154        92156 :         case SUMO_TAG_ROUTE_DISTRIBUTION:
     155        92156 :             openRouteDistribution(attrs);
     156        92156 :             break;
     157        44069 :         case SUMO_TAG_STOP:
     158        44069 :             myParamStack.push_back(addStop(attrs));
     159        43959 :             break;
     160        74485 :         case SUMO_TAG_TRIP: {
     161              :             // delete if myVehicleParameter isn't null
     162        74485 :             if (myVehicleParameter) {
     163            0 :                 delete myVehicleParameter;
     164            0 :                 myVehicleParameter = nullptr;
     165              :             }
     166              :             // parse vehicle parameters
     167        74485 :             myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
     168              :             // check if myVehicleParameter was successfully created
     169        74431 :             if (myVehicleParameter) {
     170        74431 :                 myVehicleParameter->parametersSet |= VEHPARS_FORCE_REROUTE;
     171        74431 :                 myActiveRouteID = "!" + myVehicleParameter->id;
     172              :                 // open trip
     173        74431 :                 openTrip(attrs);
     174        74431 :                 myParamStack.push_back(myVehicleParameter);
     175              :             }
     176              :             break;
     177              :         }
     178         3621 :         case SUMO_TAG_PERSONTRIP:
     179         3621 :             addPersonTrip(attrs);
     180         3608 :             break;
     181        38604 :         case SUMO_TAG_WALK:
     182        38604 :             addWalk(attrs);
     183        38582 :             break;
     184           15 :         case SUMO_TAG_INTERVAL: {
     185              :             bool ok;
     186           15 :             myBeginDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok);
     187           15 :             myEndDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok);
     188              :             break;
     189              :         }
     190         4804 :         case SUMO_TAG_RIDE:
     191         4804 :             addRide(attrs);
     192         4772 :             break;
     193          878 :         case SUMO_TAG_TRANSPORT:
     194          878 :             addTransport(attrs);
     195          864 :             break;
     196          519 :         case SUMO_TAG_TRANSHIP:
     197          519 :             addTranship(attrs);
     198          519 :             break;
     199        53788 :         case SUMO_TAG_PARAM:
     200        53788 :             addParam(attrs);
     201        53788 :             break;
     202     10075560 :         default:
     203              :             // parse embedded car following model information
     204     10075560 :             if (myCurrentVType != nullptr) {
     205           32 :                 WRITE_WARNINGF(TL("Defining car-following parameters in a nested element is deprecated in vType '%', use attributes instead!"), myCurrentVType->id);
     206           16 :                 if (!SUMOVehicleParserHelper::parseCFMParams(myCurrentVType, (SumoXMLTag)element, attrs, true)) {
     207            0 :                     if (myHardFail) {
     208            0 :                         throw ProcessError(TL("Invalid parsing embedded VType"));
     209              :                     } else {
     210            0 :                         WRITE_ERROR(TL("Invalid parsing embedded VType"));
     211              :                     }
     212              :                 }
     213              :             }
     214              :             break;
     215              :     }
     216     11264899 : }
     217              : 
     218              : 
     219              : void
     220     11254341 : SUMORouteHandler::myEndElement(int element) {
     221     11254341 :     switch (element) {
     222        43959 :         case SUMO_TAG_STOP:
     223              :             myParamStack.pop_back();
     224              :             break;
     225       395861 :         case SUMO_TAG_ROUTE:
     226       395861 :             closeRoute();
     227       395807 :             break;
     228        60349 :         case SUMO_TAG_VTYPE:
     229        60349 :             closeVType();
     230        60325 :             delete myCurrentVType;
     231        60325 :             myCurrentVType = nullptr;
     232              :             myParamStack.pop_back();
     233              :             break;
     234        41292 :         case SUMO_TAG_PERSON:
     235        41292 :             closePerson();
     236        41266 :             delete myVehicleParameter;
     237        41266 :             myVehicleParameter = nullptr;
     238              :             myParamStack.pop_back();
     239              :             break;
     240         1668 :         case SUMO_TAG_PERSONFLOW:
     241         1668 :             closePersonFlow();
     242         1659 :             delete myVehicleParameter;
     243         1659 :             myVehicleParameter = nullptr;
     244              :             myParamStack.pop_back();
     245              :             break;
     246          791 :         case SUMO_TAG_CONTAINER:
     247          791 :             closeContainer();
     248          783 :             delete myVehicleParameter;
     249          783 :             myVehicleParameter = nullptr;
     250              :             myParamStack.pop_back();
     251              :             break;
     252          307 :         case SUMO_TAG_CONTAINERFLOW:
     253          307 :             closeContainerFlow();
     254          307 :             delete myVehicleParameter;
     255          307 :             myVehicleParameter = nullptr;
     256              :             myParamStack.pop_back();
     257              :             break;
     258       353295 :         case SUMO_TAG_VEHICLE:
     259       353295 :             if (myVehicleParameter == nullptr) {
     260              :                 break;
     261              :             }
     262       353295 :             if (myVehicleParameter->repetitionNumber > 0) {
     263            0 :                 myVehicleParameter->repetitionNumber++; // for backwards compatibility
     264              :                 // it is a flow, thus no break here
     265              :                 FALLTHROUGH;
     266              :             } else {
     267       353295 :                 closeVehicle();
     268       352893 :                 delete myVehicleParameter;
     269       352893 :                 myVehicleParameter = nullptr;
     270              :                 myParamStack.pop_back();
     271              :                 break;
     272              :             }
     273              :         case SUMO_TAG_FLOW:
     274        22306 :             if (myVehicleParameter) {
     275        22306 :                 closeFlow();
     276        22283 :                 delete myVehicleParameter;
     277              :                 myParamStack.pop_back();
     278              :             }
     279        22283 :             myVehicleParameter = nullptr;
     280        22283 :             myInsertStopEdgesAt = -1;
     281        22283 :             break;
     282        73870 :         case SUMO_TAG_TRIP:
     283        73870 :             closeTrip();
     284        73265 :             delete myVehicleParameter;
     285        73265 :             myVehicleParameter = nullptr;
     286              :             myParamStack.pop_back();
     287        73265 :             myInsertStopEdgesAt = -1;
     288        73265 :             break;
     289          520 :         case SUMO_TAG_VTYPE_DISTRIBUTION:
     290          520 :             closeVehicleTypeDistribution();
     291          520 :             break;
     292        92126 :         case SUMO_TAG_ROUTE_DISTRIBUTION:
     293        92126 :             closeRouteDistribution();
     294        92126 :             break;
     295        48341 :         case SUMO_TAG_PERSONTRIP:
     296              :         case SUMO_TAG_RIDE:
     297              :         case SUMO_TAG_TRANSPORT:
     298              :         case SUMO_TAG_TRANSHIP:
     299              :         case SUMO_TAG_WALK:
     300        48341 :             if (myParamStack.size() == 2) {
     301              :                 myParamStack.pop_back();
     302              :             }
     303              :             break;
     304           15 :         case SUMO_TAG_INTERVAL:
     305           15 :             myBeginDefault = string2time(OptionsCont::getOptions().getString("begin"));
     306           15 :             myEndDefault = string2time(OptionsCont::getOptions().getString("end"));
     307           15 :             break;
     308              :         default:
     309              :             break;
     310              :     }
     311              :     myElementStack.pop_back();
     312     11253190 : }
     313              : 
     314              : 
     315              : SUMORouteHandler::StopPos
     316        92514 : SUMORouteHandler::checkStopPos(double& startPos, double& endPos, const double laneLength, const double minLength, const bool friendlyPos) {
     317        92514 :     if (minLength > laneLength) {
     318              :         return STOPPOS_INVALID_LANELENGTH;
     319              :     }
     320        92514 :     if (startPos < 0) {
     321           93 :         startPos += laneLength;
     322              :     }
     323        92514 :     if (endPos < 0) {
     324          661 :         endPos += laneLength;
     325              :     }
     326        92514 :     if ((endPos < minLength) || (endPos > laneLength)) {
     327          111 :         if (!friendlyPos) {
     328              :             return STOPPOS_INVALID_ENDPOS;
     329              :         }
     330          106 :         if (endPos < minLength) {
     331            0 :             endPos = minLength;
     332              :         }
     333          106 :         if (endPos > laneLength) {
     334          106 :             endPos = laneLength;
     335              :         }
     336              :     }
     337        92509 :     if ((startPos < 0) || (startPos > (endPos - minLength))) {
     338           57 :         if (!friendlyPos) {
     339              :             return STOPPOS_INVALID_STARTPOS;
     340              :         }
     341           57 :         if (startPos < 0) {
     342           10 :             startPos = 0;
     343              :         }
     344           57 :         if (startPos > (endPos - minLength)) {
     345           47 :             startPos = endPos - minLength;
     346              :         }
     347              :     }
     348              :     return STOPPOS_VALID;
     349              : }
     350              : 
     351              : 
     352              : bool
     353            0 : SUMORouteHandler::isStopPosValid(const double startPos, const double endPos, const double laneLength, const double minLength, const bool friendlyPos) {
     354              :     // declare dummy start and end positions
     355            0 :     double dummyStartPos = startPos;
     356            0 :     double dummyEndPos = endPos;
     357              :     // return checkStopPos
     358            0 :     return (checkStopPos(dummyStartPos, dummyEndPos, laneLength, minLength, friendlyPos) == STOPPOS_VALID);
     359              : }
     360              : 
     361              : 
     362              : SUMOTime
     363       100564 : SUMORouteHandler::getFirstDepart() const {
     364       100564 :     return myFirstDepart;
     365              : }
     366              : 
     367              : 
     368              : SUMOTime
     369      2950046 : SUMORouteHandler::getLastDepart() const {
     370      2950046 :     return myLastDepart;
     371              : }
     372              : 
     373              : 
     374              : void
     375        53788 : SUMORouteHandler::addParam(const SUMOSAXAttributes& attrs) {
     376        53788 :     bool ok = true;
     377        53788 :     const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
     378              :     // only continue if key isn't empty
     379        53788 :     if (ok && (key.size() > 0)) {
     380              :         // circumventing empty string test
     381        53788 :         const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
     382              :         // add parameter in current created element
     383        53788 :         if (!myParamStack.empty()) {
     384        13496 :             myParamStack.back()->setParameter(key, val);
     385              :         }
     386              :     }
     387        53788 : }
     388              : 
     389              : 
     390              : bool
     391        44053 : SUMORouteHandler::parseStop(SUMOVehicleParameter::Stop& stop, const SUMOSAXAttributes& attrs, std::string errorSuffix, MsgHandler* const errorOutput) {
     392        44053 :     stop.parametersSet = 0;
     393        44053 :     if (attrs.hasAttribute(SUMO_ATTR_ARRIVAL)) {
     394          381 :         stop.parametersSet |= STOP_ARRIVAL_SET;
     395              :     }
     396        44053 :     if (attrs.hasAttribute(SUMO_ATTR_DURATION)) {
     397        33001 :         stop.parametersSet |= STOP_DURATION_SET;
     398              :     }
     399        44053 :     if (attrs.hasAttribute(SUMO_ATTR_UNTIL)) {
     400        11787 :         stop.parametersSet |= STOP_UNTIL_SET;
     401              :     }
     402        44053 :     if (attrs.hasAttribute(SUMO_ATTR_STARTED)) {
     403         3191 :         stop.parametersSet |= STOP_STARTED_SET;
     404              :     }
     405        44053 :     if (attrs.hasAttribute(SUMO_ATTR_ENDED)) {
     406         2979 :         stop.parametersSet |= STOP_ENDED_SET;
     407              :     }
     408        44053 :     if (attrs.hasAttribute(SUMO_ATTR_EXTENSION)) {
     409          440 :         stop.parametersSet |= STOP_EXTENSION_SET;
     410              :     }
     411        44053 :     if (attrs.hasAttribute(SUMO_ATTR_ENDPOS)) {
     412         7978 :         stop.parametersSet |= STOP_END_SET;
     413              :     }
     414        44053 :     if (attrs.hasAttribute(SUMO_ATTR_STARTPOS)) {
     415         1349 :         stop.parametersSet |= STOP_START_SET;
     416              :     }
     417        44053 :     if (attrs.hasAttribute(SUMO_ATTR_POSITION_LAT)) {
     418          121 :         stop.parametersSet |= STOP_POSLAT_SET;
     419              :     }
     420        44053 :     if (attrs.hasAttribute(SUMO_ATTR_TRIGGERED)) {
     421         1218 :         stop.parametersSet |= STOP_TRIGGER_SET;
     422              :     }
     423              :     // legacy attribute
     424        44053 :     if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_TRIGGERED)) {
     425           56 :         stop.parametersSet |= STOP_TRIGGER_SET;
     426              :     }
     427        44053 :     if (attrs.hasAttribute(SUMO_ATTR_PARKING)) {
     428          959 :         stop.parametersSet |= STOP_PARKING_SET;
     429              :     }
     430        44053 :     if (attrs.hasAttribute(SUMO_ATTR_EXPECTED)) {
     431          242 :         stop.parametersSet |= STOP_EXPECTED_SET;
     432              :     }
     433        44053 :     if (attrs.hasAttribute(SUMO_ATTR_PERMITTED)) {
     434          320 :         stop.parametersSet |= STOP_PERMITTED_SET;
     435              :     }
     436        44053 :     if (attrs.hasAttribute(SUMO_ATTR_EXPECTED_CONTAINERS)) {
     437           82 :         stop.parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
     438              :     }
     439        44053 :     if (attrs.hasAttribute(SUMO_ATTR_TRIP_ID)) {
     440          408 :         stop.parametersSet |= STOP_TRIP_ID_SET;
     441              :     }
     442        44053 :     if (attrs.hasAttribute(SUMO_ATTR_SPLIT)) {
     443          222 :         stop.parametersSet |= STOP_SPLIT_SET;
     444              :     }
     445        44053 :     if (attrs.hasAttribute(SUMO_ATTR_JOIN)) {
     446          117 :         stop.parametersSet |= STOP_JOIN_SET;
     447              :     }
     448        44053 :     if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
     449          363 :         stop.parametersSet |= STOP_LINE_SET;
     450              :     }
     451        44053 :     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
     452          617 :         stop.parametersSet |= STOP_SPEED_SET;
     453              :     }
     454        44053 :     if (attrs.hasAttribute(SUMO_ATTR_ONDEMAND)) {
     455          171 :         stop.parametersSet |= STOP_ONDEMAND_SET;
     456              :     }
     457        44053 :     if (attrs.hasAttribute(SUMO_ATTR_JUMP)) {
     458          365 :         stop.parametersSet |= STOP_JUMP_SET;
     459              :     }
     460        44053 :     bool ok = true;
     461        88106 :     stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
     462        44053 :     stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop);
     463        44053 :     stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
     464        44053 :     stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
     465        44053 :     stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
     466        88106 :     stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
     467        44053 :     if (stop.busstop != "") {
     468        29061 :         errorSuffix = " at '" + stop.busstop + "'" + errorSuffix;
     469        34366 :     } else if (stop.chargingStation != "") {
     470         3246 :         errorSuffix = " at '" + stop.chargingStation + "'" + errorSuffix;
     471        33284 :     } else if (stop.overheadWireSegment != "") {
     472            0 :         errorSuffix = " at '" + stop.overheadWireSegment + "'" + errorSuffix;
     473        33284 :     } else if (stop.containerstop != "") {
     474         1632 :         errorSuffix = " at '" + stop.containerstop + "'" + errorSuffix;
     475        32740 :     } else if (stop.parkingarea != "") {
     476        25806 :         errorSuffix = " at '" + stop.parkingarea + "'" + errorSuffix;
     477        24138 :     } else if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
     478        68160 :         errorSuffix = " on lane '" + attrs.get<std::string>(SUMO_ATTR_LANE, nullptr, ok) + "'" + errorSuffix;
     479         1418 :     } else if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
     480         3978 :         errorSuffix = " on edge '" + attrs.get<std::string>(SUMO_ATTR_EDGE, nullptr, ok) + "'" + errorSuffix;
     481              :     } else {
     482          184 :         errorSuffix = " at undefined location" + errorSuffix;
     483              :     }
     484              :     // speed for counting as stopped
     485        44053 :     stop.speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, 0);
     486        44053 :     if (stop.speed < 0) {
     487           12 :         errorOutput->inform(TLF("Speed cannot be negative for stop%.", errorSuffix));
     488            6 :         return false;
     489              :     }
     490              : 
     491              :     // get the standing duration
     492        44047 :     bool expectTrigger = !attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL) && !attrs.hasAttribute(SUMO_ATTR_SPEED);
     493        44047 :     std::vector<std::string> triggers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_TRIGGERED, nullptr, ok);
     494              :     // legacy
     495        44047 :     if (attrs.getOpt<bool>(SUMO_ATTR_CONTAINER_TRIGGERED, nullptr, ok, false)) {
     496          112 :         triggers.push_back(toString(SUMO_TAG_CONTAINER));
     497              :     }
     498        44047 :     SUMOVehicleParameter::parseStopTriggers(triggers, expectTrigger, stop);
     499        44047 :     stop.arrival = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ARRIVAL, nullptr, ok, -1);
     500        44047 :     stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
     501        44047 :     stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, -1);
     502        44047 :     if (!expectTrigger && (!ok || (stop.duration < 0 && stop.until < 0 && stop.speed == 0))) {
     503           36 :         errorOutput->inform(TLF("Invalid duration or end time is given for a stop%.", errorSuffix));
     504           12 :         return false;
     505              :     }
     506        44035 :     if (triggers.size() > 0 && stop.speed > 0) {
     507            9 :         errorOutput->inform(TLF("Triggers and waypoints cannot be combined%.", errorSuffix));
     508            3 :         return false;
     509              :     }
     510        44032 :     stop.extension = attrs.getOptSUMOTimeReporting(SUMO_ATTR_EXTENSION, nullptr, ok, -1);
     511        44032 :     const bool defaultParking = (stop.triggered || stop.containerTriggered || stop.parkingarea != "");
     512        44032 :     stop.parking = attrs.getOpt<ParkingType>(SUMO_ATTR_PARKING, nullptr, ok, defaultParking ? ParkingType::OFFROAD : ParkingType::ONROAD);
     513        44032 :     if ((stop.parkingarea != "") && (stop.parking == ParkingType::ONROAD)) {
     514            0 :         WRITE_WARNINGF(TL("Stop at parkingArea overrides attribute 'parking' for stop%."), errorSuffix);
     515            0 :         stop.parking = ParkingType::OFFROAD;
     516              :     }
     517              : 
     518              :     // expected persons
     519        44032 :     const std::vector<std::string>& expected = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED, nullptr, ok);
     520              :     stop.awaitedPersons.insert(expected.begin(), expected.end());
     521        44032 :     if (stop.awaitedPersons.size() > 0) {
     522          242 :         stop.triggered = true;
     523          242 :         if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
     524           95 :             stop.parking = ParkingType::OFFROAD;
     525              :         }
     526              :     }
     527              : 
     528              :     // permitted transportables
     529        44032 :     const std::vector<std::string>& permitted = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_PERMITTED, nullptr, ok);
     530              :     stop.permitted.insert(permitted.begin(), permitted.end());
     531              : 
     532              :     // expected containers
     533        44032 :     const std::vector<std::string>& expectedContainers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED_CONTAINERS, nullptr, ok);
     534              :     stop.awaitedContainers.insert(expectedContainers.begin(), expectedContainers.end());
     535        44032 :     if (stop.awaitedContainers.size() > 0) {
     536           82 :         stop.containerTriggered = true;
     537           82 :         if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
     538           60 :             stop.parking = ParkingType::OFFROAD;
     539              :         }
     540              :     }
     541              :     // public transport trip id
     542        44032 :     stop.tripId = attrs.getOpt<std::string>(SUMO_ATTR_TRIP_ID, nullptr, ok, "");
     543        44032 :     stop.split = attrs.getOpt<std::string>(SUMO_ATTR_SPLIT, nullptr, ok, "");
     544        44032 :     stop.join = attrs.getOpt<std::string>(SUMO_ATTR_JOIN, nullptr, ok, "");
     545        44032 :     stop.line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, nullptr, ok, "");
     546              : 
     547        44032 :     const std::string idx = attrs.getOpt<std::string>(SUMO_ATTR_INDEX, nullptr, ok, "end");
     548        44032 :     if (idx == "end") {
     549        43831 :         stop.index = STOP_INDEX_END;
     550          201 :     } else if (idx == "fit") {
     551           14 :         stop.index = STOP_INDEX_FIT;
     552              :     } else {
     553          187 :         stop.index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
     554          187 :         if (!ok || stop.index < 0) {
     555           18 :             errorOutput->inform(TLF("Invalid 'index' for stop%.", errorSuffix));
     556            6 :             return false;
     557              :         }
     558              :     }
     559        44026 :     stop.started = attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1);
     560        44026 :     stop.ended = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1);
     561        44026 :     stop.posLat = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, nullptr, ok, INVALID_DOUBLE);
     562        44026 :     stop.actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
     563        44026 :     stop.onDemand = attrs.getOpt<bool>(SUMO_ATTR_ONDEMAND, nullptr, ok, false);
     564        44026 :     stop.jump = attrs.getOptSUMOTimeReporting(SUMO_ATTR_JUMP, nullptr, ok, -1);
     565        44026 :     stop.collision = attrs.getOpt<bool>(SUMO_ATTR_COLLISION, nullptr, ok, false);
     566        44026 :     return true;
     567        44047 : }
     568              : 
     569              : 
     570              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1