LCOV - code coverage report
Current view: top level - src/utils/vehicle - SUMORouteHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.6 % 340 325
Test Date: 2025-11-13 15:38:19 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-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    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/common/FileHelpers.h>
      27              : #include <utils/options/OptionsCont.h>
      28              : #include <utils/vehicle/SUMOVTypeParameter.h>
      29              : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      30              : #include <utils/xml/XMLSubSys.h>
      31              : 
      32              : #include "SUMORouteHandler.h"
      33              : 
      34              : 
      35              : // ===========================================================================
      36              : // method definitions
      37              : // ===========================================================================
      38              : 
      39        75482 : SUMORouteHandler::SUMORouteHandler(const std::string& file, const std::string& expectedRoot, const bool hardFail) :
      40              :     SUMOSAXHandler(file, expectedRoot),
      41        75482 :     myHardFail(hardFail),
      42        75482 :     myVehicleParameter(nullptr),
      43        75482 :     myLastDepart(-1),
      44        75482 :     myActiveRouteColor(nullptr),
      45        75482 :     myCurrentCosts(0.),
      46        75482 :     myCurrentVType(nullptr),
      47       226444 :     myBeginDefault(OptionsCont::getOptions().exists("begin") ? string2time(OptionsCont::getOptions().getString("begin")) : 0),
      48       226444 :     myEndDefault(OptionsCont::getOptions().exists("end") ? string2time(OptionsCont::getOptions().getString("end")) : -1),
      49        75482 :     myFirstDepart(-1),
      50        75482 :     myInsertStopEdgesAt(-1),
      51       150964 :     myAllowInternalRoutes(false) {
      52        75482 : }
      53              : 
      54              : 
      55        75058 : SUMORouteHandler::~SUMORouteHandler() {
      56        75058 :     delete myVehicleParameter;
      57        75058 :     delete myCurrentVType;
      58        75058 : }
      59              : 
      60              : 
      61              : bool
      62       606450 : SUMORouteHandler::checkLastDepart() {
      63       606450 :     if (myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
      64       605510 :         if (myVehicleParameter->depart < myLastDepart) {
      65           16 :             WRITE_WARNINGF(TL("Route file should be sorted by departure time, ignoring '%'!"), myVehicleParameter->id);
      66            8 :             return false;
      67              :         }
      68              :     }
      69              :     return true;
      70              : }
      71              : 
      72              : 
      73              : void
      74       655342 : SUMORouteHandler::registerLastDepart() {
      75              :     // register only non public transport to parse all public transport lines in advance
      76       655342 :     if (myVehicleParameter && myVehicleParameter->line == "" && myVehicleParameter->departProcedure == DepartDefinition::GIVEN) {
      77       649727 :         myLastDepart = myVehicleParameter->depart;
      78       649727 :         if (myFirstDepart == -1) {
      79        38052 :             myFirstDepart = myLastDepart;
      80              :         }
      81              :     }
      82              :     // else: we don't know when this vehicle will depart. keep the previous known depart time
      83       655342 : }
      84              : 
      85              : 
      86              : void
      87     10736483 : SUMORouteHandler::myStartElement(int element, const SUMOSAXAttributes& attrs) {
      88     10736483 :     myElementStack.push_back(element);
      89     10736483 :     switch (element) {
      90       399993 :         case SUMO_TAG_VEHICLE:
      91              :         case SUMO_TAG_PERSON:
      92              :         case SUMO_TAG_CONTAINER:
      93              :             // if myVehicleParameter is nullptr this will do nothing
      94       399993 :             delete myVehicleParameter;
      95              :             // we set to nullptr to have a consistent state if the parsing fails
      96       399993 :             myVehicleParameter = nullptr;
      97       399993 :             myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
      98       399733 :             myParamStack.push_back(myVehicleParameter);
      99       399733 :             if (element != SUMO_TAG_VEHICLE) {
     100        44583 :                 addTransportable(attrs, element == SUMO_TAG_PERSON);
     101              :             }
     102              :             break;
     103        20604 :         case SUMO_TAG_FLOW:
     104              :             // delete if myVehicleParameter isn't null
     105        20604 :             if (myVehicleParameter) {
     106            0 :                 delete myVehicleParameter;
     107            0 :                 myVehicleParameter = nullptr;
     108              :             }
     109              :             // parse vehicle parameters
     110              :             // might be called to parse vehicles from additional file in the
     111              :             // context of quickReload. In this case, rerouter flows must be ignored
     112        20604 :             if (myElementStack.size() == 1 || myElementStack[myElementStack.size() - 2] != SUMO_TAG_CALIBRATOR) {
     113        20604 :                 myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes(SUMO_TAG_FLOW, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
     114              :             }
     115              :             // check if myVehicleParameter was successfully created
     116        20486 :             if (myVehicleParameter) {
     117              :                 // check tag
     118        20486 :                 if (myVehicleParameter->routeid.empty()) {
     119              :                     // open a route flow (It could be a flow with embedded route)
     120        11874 :                     openFlow(attrs);
     121              :                 } else {
     122              :                     // open a route flow
     123         8612 :                     openRouteFlow(attrs);
     124              :                 }
     125        20486 :                 myParamStack.push_back(myVehicleParameter);
     126              :             }
     127              :             break;
     128         2292 :         case SUMO_TAG_PERSONFLOW:
     129              :         case SUMO_TAG_CONTAINERFLOW:
     130              :             // delete if myVehicleParameter isn't null
     131         2292 :             if (myVehicleParameter) {
     132            0 :                 delete myVehicleParameter;
     133            0 :                 myVehicleParameter = nullptr;
     134              :             }
     135              :             // create a new flow
     136         2292 :             myVehicleParameter = SUMOVehicleParserHelper::parseFlowAttributes((SumoXMLTag)element, attrs, myHardFail, true, myBeginDefault, myEndDefault, myAllowInternalRoutes);
     137         2292 :             myParamStack.push_back(myVehicleParameter);
     138         2292 :             break;
     139        62531 :         case SUMO_TAG_VTYPE:
     140              :             // delete if myCurrentVType isn't null
     141        62531 :             if (myCurrentVType != nullptr) {
     142            4 :                 delete myCurrentVType;
     143            4 :                 myCurrentVType = nullptr;
     144              :             }
     145              :             // create a new vType
     146        62531 :             myCurrentVType = SUMOVehicleParserHelper::beginVTypeParsing(attrs, myHardFail, getFileName());
     147        62501 :             myParamStack.push_back(myCurrentVType);
     148        62501 :             break;
     149          527 :         case SUMO_TAG_VTYPE_DISTRIBUTION:
     150          527 :             openVehicleTypeDistribution(attrs);
     151          527 :             break;
     152       384381 :         case SUMO_TAG_ROUTE:
     153       384381 :             openRoute(attrs);
     154       384329 :             break;
     155        92346 :         case SUMO_TAG_ROUTE_DISTRIBUTION:
     156        92346 :             openRouteDistribution(attrs);
     157        92346 :             break;
     158        39278 :         case SUMO_TAG_STOP:
     159        39278 :             myParamStack.push_back(addStop(attrs));
     160        39166 :             break;
     161       235941 :         case SUMO_TAG_TRIP: {
     162              :             // delete if myVehicleParameter isn't null
     163       235941 :             if (myVehicleParameter) {
     164            0 :                 delete myVehicleParameter;
     165            0 :                 myVehicleParameter = nullptr;
     166              :             }
     167              :             // parse vehicle parameters
     168       235941 :             myVehicleParameter = SUMOVehicleParserHelper::parseVehicleAttributes(element, attrs, myHardFail, false, false, myAllowInternalRoutes);
     169              :             // check if myVehicleParameter was successfully created
     170       235887 :             if (myVehicleParameter) {
     171       235887 :                 myVehicleParameter->parametersSet |= VEHPARS_FORCE_REROUTE;
     172       235887 :                 myActiveRouteID = "!" + myVehicleParameter->id;
     173              :                 // open trip
     174       235887 :                 openTrip(attrs);
     175       235887 :                 myParamStack.push_back(myVehicleParameter);
     176              :             }
     177              :             break;
     178              :         }
     179         4797 :         case SUMO_TAG_PERSONTRIP:
     180         4797 :             addPersonTrip(attrs);
     181         4784 :             break;
     182        39839 :         case SUMO_TAG_WALK:
     183        39839 :             addWalk(attrs);
     184        39817 :             break;
     185           15 :         case SUMO_TAG_INTERVAL: {
     186              :             bool ok;
     187           15 :             myBeginDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok);
     188           15 :             myEndDefault = attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok);
     189              :             break;
     190              :         }
     191         5098 :         case SUMO_TAG_RIDE:
     192         5098 :             addRide(attrs);
     193         5066 :             break;
     194          992 :         case SUMO_TAG_TRANSPORT:
     195          992 :             addTransport(attrs);
     196          978 :             break;
     197          519 :         case SUMO_TAG_TRANSHIP:
     198          519 :             addTranship(attrs);
     199          519 :             break;
     200        56016 :         case SUMO_TAG_PARAM:
     201        56016 :             addParam(attrs);
     202        56016 :             break;
     203      9391314 :         default:
     204              :             // parse embedded car following model information
     205      9391314 :             if (myCurrentVType != nullptr) {
     206           32 :                 WRITE_WARNINGF(TL("Defining car-following parameters in a nested element is deprecated in vType '%', use attributes instead!"), myCurrentVType->id);
     207           16 :                 if (!SUMOVehicleParserHelper::parseCFMParams(myCurrentVType, (SumoXMLTag)element, attrs, true)) {
     208            0 :                     if (myHardFail) {
     209            0 :                         throw ProcessError(TL("Invalid parsing embedded VType"));
     210              :                     } else {
     211            0 :                         WRITE_ERROR(TL("Invalid parsing embedded VType"));
     212              :                     }
     213              :                 }
     214              :             }
     215              :             break;
     216              :     }
     217     10735776 : }
     218              : 
     219              : 
     220              : void
     221     10729100 : SUMORouteHandler::myEndElement(int element) {
     222     10729100 :     switch (element) {
     223        39166 :         case SUMO_TAG_STOP:
     224              :             myParamStack.pop_back();
     225              :             break;
     226       384329 :         case SUMO_TAG_ROUTE:
     227       384329 :             closeRoute();
     228       384275 :             break;
     229        62497 :         case SUMO_TAG_VTYPE:
     230        62497 :             closeVType();
     231        62473 :             delete myCurrentVType;
     232        62473 :             myCurrentVType = nullptr;
     233              :             myParamStack.pop_back();
     234              :             break;
     235        43634 :         case SUMO_TAG_PERSON:
     236        43634 :             closePerson();
     237        43608 :             delete myVehicleParameter;
     238        43608 :             myVehicleParameter = nullptr;
     239              :             myParamStack.pop_back();
     240              :             break;
     241         1925 :         case SUMO_TAG_PERSONFLOW:
     242         1925 :             closePersonFlow();
     243         1913 :             delete myVehicleParameter;
     244         1913 :             myVehicleParameter = nullptr;
     245              :             myParamStack.pop_back();
     246              :             break;
     247          849 :         case SUMO_TAG_CONTAINER:
     248          849 :             closeContainer();
     249          841 :             delete myVehicleParameter;
     250          841 :             myVehicleParameter = nullptr;
     251              :             myParamStack.pop_back();
     252              :             break;
     253          363 :         case SUMO_TAG_CONTAINERFLOW:
     254          363 :             closeContainerFlow();
     255          363 :             delete myVehicleParameter;
     256          363 :             myVehicleParameter = nullptr;
     257              :             myParamStack.pop_back();
     258              :             break;
     259       355002 :         case SUMO_TAG_VEHICLE:
     260       355002 :             if (myVehicleParameter == nullptr) {
     261              :                 break;
     262              :             }
     263       355002 :             if (myVehicleParameter->repetitionNumber > 0) {
     264            0 :                 myVehicleParameter->repetitionNumber++; // for backwards compatibility
     265              :                 // it is a flow, thus no break here
     266              :                 FALLTHROUGH;
     267              :             } else {
     268       355002 :                 closeVehicle();
     269       354916 :                 delete myVehicleParameter;
     270       354916 :                 myVehicleParameter = nullptr;
     271              :                 myParamStack.pop_back();
     272              :                 break;
     273              :             }
     274              :         case SUMO_TAG_FLOW:
     275        20484 :             if (myVehicleParameter) {
     276        20484 :                 closeFlow();
     277        20477 :                 delete myVehicleParameter;
     278              :                 myParamStack.pop_back();
     279              :             }
     280        20477 :             myVehicleParameter = nullptr;
     281        20477 :             myInsertStopEdgesAt = -1;
     282        20477 :             break;
     283       235839 :         case SUMO_TAG_TRIP:
     284       235839 :             closeTrip();
     285       235826 :             delete myVehicleParameter;
     286       235826 :             myVehicleParameter = nullptr;
     287              :             myParamStack.pop_back();
     288       235826 :             myInsertStopEdgesAt = -1;
     289       235826 :             break;
     290          524 :         case SUMO_TAG_VTYPE_DISTRIBUTION:
     291          524 :             closeVehicleTypeDistribution();
     292          524 :             break;
     293        92316 :         case SUMO_TAG_ROUTE_DISTRIBUTION:
     294        92316 :             closeRouteDistribution();
     295        92316 :             break;
     296        51160 :         case SUMO_TAG_PERSONTRIP:
     297              :         case SUMO_TAG_RIDE:
     298              :         case SUMO_TAG_TRANSPORT:
     299              :         case SUMO_TAG_TRANSHIP:
     300              :         case SUMO_TAG_WALK:
     301        51160 :             if (myParamStack.size() == 2) {
     302              :                 myParamStack.pop_back();
     303              :             }
     304              :             break;
     305           15 :         case SUMO_TAG_INTERVAL:
     306           15 :             myBeginDefault = string2time(OptionsCont::getOptions().getString("begin"));
     307           15 :             myEndDefault = string2time(OptionsCont::getOptions().getString("end"));
     308           15 :             break;
     309              :         default:
     310              :             break;
     311              :     }
     312              :     myElementStack.pop_back();
     313     10728870 : }
     314              : 
     315              : 
     316              : SUMORouteHandler::StopPos
     317        84085 : SUMORouteHandler::checkStopPos(double& startPos, double& endPos, const double laneLength, const double minLength, const bool friendlyPos) {
     318        84085 :     if (minLength > laneLength) {
     319              :         return STOPPOS_INVALID_LANELENGTH;
     320              :     }
     321        84085 :     if (startPos < 0) {
     322          145 :         startPos += laneLength;
     323              :     }
     324        84085 :     if (endPos < 0) {
     325          993 :         endPos += laneLength;
     326              :     }
     327        84085 :     if ((endPos < minLength) || (endPos > laneLength)) {
     328          126 :         if (!friendlyPos) {
     329              :             return STOPPOS_INVALID_ENDPOS;
     330              :         }
     331          121 :         if (endPos < minLength) {
     332            3 :             endPos = minLength;
     333              :         }
     334          121 :         if (endPos > laneLength) {
     335          118 :             endPos = laneLength;
     336              :         }
     337              :     }
     338        84080 :     if ((startPos < 0) || (startPos > (endPos - minLength))) {
     339           63 :         if (!friendlyPos) {
     340              :             return STOPPOS_INVALID_STARTPOS;
     341              :         }
     342           63 :         if (startPos < 0) {
     343           13 :             startPos = 0;
     344              :         }
     345           63 :         if (startPos > (endPos - minLength)) {
     346           50 :             startPos = endPos - minLength;
     347              :         }
     348              :     }
     349              :     return STOPPOS_VALID;
     350              : }
     351              : 
     352              : 
     353              : bool
     354            0 : SUMORouteHandler::isStopPosValid(const double startPos, const double endPos, const double laneLength, const double minLength, const bool friendlyPos) {
     355              :     // declare dummy start and end positions
     356            0 :     double dummyStartPos = startPos;
     357            0 :     double dummyEndPos = endPos;
     358              :     // return checkStopPos
     359            0 :     return (checkStopPos(dummyStartPos, dummyEndPos, laneLength, minLength, friendlyPos) == STOPPOS_VALID);
     360              : }
     361              : 
     362              : 
     363              : SUMOTime
     364        92786 : SUMORouteHandler::getFirstDepart() const {
     365        92786 :     return myFirstDepart;
     366              : }
     367              : 
     368              : 
     369              : SUMOTime
     370      3204972 : SUMORouteHandler::getLastDepart() const {
     371      3204972 :     return myLastDepart;
     372              : }
     373              : 
     374              : 
     375              : void
     376        56016 : SUMORouteHandler::addParam(const SUMOSAXAttributes& attrs) {
     377        56016 :     bool ok = true;
     378        56016 :     const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
     379              :     // only continue if key isn't empty
     380        56016 :     if (ok && (key.size() > 0)) {
     381              :         // circumventing empty string test
     382        56016 :         std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
     383              :         // check special params that must be interpreted as relative paths
     384        47257 :         if ((myVehicleParameter != nullptr || myCurrentVType != nullptr)
     385        61955 :                 && (key == "device.toc.file" || key == "device.ssm.file")) {
     386          786 :             val = FileHelpers::checkForRelativity(val, getFileName());
     387              :         }
     388              :         // add parameter in current created element
     389        56016 :         if (!myParamStack.empty()) {
     390        14698 :             myParamStack.back()->setParameter(key, val);
     391              :         }
     392              :     }
     393        56016 : }
     394              : 
     395              : 
     396              : bool
     397        39262 : SUMORouteHandler::parseStop(SUMOVehicleParameter::Stop& stop, const SUMOSAXAttributes& attrs, std::string errorSuffix, MsgHandler* const errorOutput) {
     398        39262 :     stop.parametersSet = 0;
     399        39262 :     if (attrs.hasAttribute(SUMO_ATTR_ARRIVAL)) {
     400          398 :         stop.parametersSet |= STOP_ARRIVAL_SET;
     401              :     }
     402        39262 :     if (attrs.hasAttribute(SUMO_ATTR_DURATION)) {
     403        21323 :         stop.parametersSet |= STOP_DURATION_SET;
     404              :     }
     405        39262 :     if (attrs.hasAttribute(SUMO_ATTR_UNTIL)) {
     406        19803 :         stop.parametersSet |= STOP_UNTIL_SET;
     407              :     }
     408        39262 :     if (attrs.hasAttribute(SUMO_ATTR_STARTED)) {
     409         6576 :         stop.parametersSet |= STOP_STARTED_SET;
     410              :     }
     411        39262 :     if (attrs.hasAttribute(SUMO_ATTR_ENDED)) {
     412         6089 :         stop.parametersSet |= STOP_ENDED_SET;
     413              :     }
     414        39262 :     if (attrs.hasAttribute(SUMO_ATTR_EXTENSION)) {
     415          464 :         stop.parametersSet |= STOP_EXTENSION_SET;
     416              :     }
     417        39262 :     if (attrs.hasAttribute(SUMO_ATTR_ENDPOS)) {
     418         8572 :         stop.parametersSet |= STOP_END_SET;
     419              :     }
     420        39262 :     if (attrs.hasAttribute(SUMO_ATTR_STARTPOS)) {
     421         1511 :         stop.parametersSet |= STOP_START_SET;
     422              :     }
     423        39262 :     if (attrs.hasAttribute(SUMO_ATTR_POSITION_LAT)) {
     424          125 :         stop.parametersSet |= STOP_POSLAT_SET;
     425              :     }
     426        39262 :     if (attrs.hasAttribute(SUMO_ATTR_TRIGGERED)) {
     427         1466 :         stop.parametersSet |= STOP_TRIGGER_SET;
     428              :     }
     429              :     // legacy attribute
     430        39262 :     if (attrs.hasAttribute(SUMO_ATTR_CONTAINER_TRIGGERED)) {
     431           56 :         stop.parametersSet |= STOP_TRIGGER_SET;
     432              :     }
     433        39262 :     if (attrs.hasAttribute(SUMO_ATTR_PARKING)) {
     434          913 :         stop.parametersSet |= STOP_PARKING_SET;
     435              :     }
     436        39262 :     if (attrs.hasAttribute(SUMO_ATTR_EXPECTED)) {
     437          242 :         stop.parametersSet |= STOP_EXPECTED_SET;
     438              :     }
     439        39262 :     if (attrs.hasAttribute(SUMO_ATTR_PERMITTED)) {
     440          344 :         stop.parametersSet |= STOP_PERMITTED_SET;
     441              :     }
     442        39262 :     if (attrs.hasAttribute(SUMO_ATTR_EXPECTED_CONTAINERS)) {
     443           77 :         stop.parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
     444              :     }
     445        39262 :     if (attrs.hasAttribute(SUMO_ATTR_TRIP_ID)) {
     446          432 :         stop.parametersSet |= STOP_TRIP_ID_SET;
     447              :     }
     448        39262 :     if (attrs.hasAttribute(SUMO_ATTR_SPLIT)) {
     449          356 :         stop.parametersSet |= STOP_SPLIT_SET;
     450              :     }
     451        39262 :     if (attrs.hasAttribute(SUMO_ATTR_JOIN)) {
     452          116 :         stop.parametersSet |= STOP_JOIN_SET;
     453              :     }
     454        39262 :     if (attrs.hasAttribute(SUMO_ATTR_LINE)) {
     455          387 :         stop.parametersSet |= STOP_LINE_SET;
     456              :     }
     457        39262 :     if (attrs.hasAttribute(SUMO_ATTR_SPEED)) {
     458          642 :         stop.parametersSet |= STOP_SPEED_SET;
     459              :     }
     460        39262 :     if (attrs.hasAttribute(SUMO_ATTR_ONDEMAND)) {
     461          171 :         stop.parametersSet |= STOP_ONDEMAND_SET;
     462              :     }
     463        39262 :     if (attrs.hasAttribute(SUMO_ATTR_PRIORITY)) {
     464           60 :         stop.parametersSet |= STOP_PRIORITY_SET;
     465              :     }
     466        39262 :     if (attrs.hasAttribute(SUMO_ATTR_JUMP)) {
     467          545 :         stop.parametersSet |= STOP_JUMP_SET;
     468              :     }
     469        39262 :     if (attrs.hasAttribute(SUMO_ATTR_JUMP_UNTIL)) {
     470            7 :         stop.parametersSet |= STOP_JUMP_UNTIL_SET;
     471              :     }
     472        39262 :     bool ok = true;
     473        78524 :     stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_BUS_STOP, nullptr, ok, "");
     474        39262 :     stop.busstop = attrs.getOpt<std::string>(SUMO_ATTR_TRAIN_STOP, nullptr, ok, stop.busstop);
     475        39262 :     stop.chargingStation = attrs.getOpt<std::string>(SUMO_ATTR_CHARGING_STATION, nullptr, ok, "");
     476        39262 :     stop.overheadWireSegment = attrs.getOpt<std::string>(SUMO_ATTR_OVERHEAD_WIRE_SEGMENT, nullptr, ok, "");
     477        39262 :     stop.containerstop = attrs.getOpt<std::string>(SUMO_ATTR_CONTAINER_STOP, nullptr, ok, "");
     478        78524 :     stop.parkingarea = attrs.getOpt<std::string>(SUMO_ATTR_PARKING_AREA, nullptr, ok, "");
     479        39262 :     if (stop.busstop != "") {
     480        33417 :         errorSuffix = " at '" + stop.busstop + "'" + errorSuffix;
     481        28123 :     } else if (stop.chargingStation != "") {
     482         3276 :         errorSuffix = " at '" + stop.chargingStation + "'" + errorSuffix;
     483        27031 :     } else if (stop.overheadWireSegment != "") {
     484            0 :         errorSuffix = " at '" + stop.overheadWireSegment + "'" + errorSuffix;
     485        27031 :     } else if (stop.containerstop != "") {
     486         1848 :         errorSuffix = " at '" + stop.containerstop + "'" + errorSuffix;
     487        26415 :     } else if (stop.parkingarea != "") {
     488        45921 :         errorSuffix = " at '" + stop.parkingarea + "'" + errorSuffix;
     489        11108 :     } else if (attrs.hasAttribute(SUMO_ATTR_LANE)) {
     490        28362 :         errorSuffix = " on lane '" + attrs.get<std::string>(SUMO_ATTR_LANE, nullptr, ok) + "'" + errorSuffix;
     491         1654 :     } else if (attrs.hasAttribute(SUMO_ATTR_EDGE)) {
     492         4662 :         errorSuffix = " on edge '" + attrs.get<std::string>(SUMO_ATTR_EDGE, nullptr, ok) + "'" + errorSuffix;
     493              :     } else {
     494          200 :         errorSuffix = " at undefined location" + errorSuffix;
     495              :     }
     496              :     // speed for counting as stopped
     497        39262 :     stop.speed = attrs.getOpt<double>(SUMO_ATTR_SPEED, nullptr, ok, 0);
     498        39262 :     if (stop.speed < 0) {
     499           12 :         errorOutput->inform(TLF("Speed cannot be negative for stop%.", errorSuffix));
     500            6 :         return false;
     501              :     }
     502              : 
     503              :     // get the standing duration
     504        39256 :     bool expectTrigger = !attrs.hasAttribute(SUMO_ATTR_DURATION) && !attrs.hasAttribute(SUMO_ATTR_UNTIL) && !attrs.hasAttribute(SUMO_ATTR_SPEED);
     505        39256 :     std::vector<std::string> triggers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_TRIGGERED, nullptr, ok);
     506              :     // legacy
     507        39256 :     if (attrs.getOpt<bool>(SUMO_ATTR_CONTAINER_TRIGGERED, nullptr, ok, false)) {
     508          112 :         triggers.push_back(toString(SUMO_TAG_CONTAINER));
     509              :     }
     510        39256 :     SUMOVehicleParameter::parseStopTriggers(triggers, expectTrigger, stop);
     511        39256 :     stop.arrival = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ARRIVAL, nullptr, ok, -1);
     512        39256 :     stop.duration = attrs.getOptSUMOTimeReporting(SUMO_ATTR_DURATION, nullptr, ok, -1);
     513        39256 :     stop.until = attrs.getOptSUMOTimeReporting(SUMO_ATTR_UNTIL, nullptr, ok, -1);
     514        39256 :     if (!expectTrigger && (!ok || (stop.duration < 0 && stop.until < 0 && stop.speed == 0))) {
     515           36 :         errorOutput->inform(TLF("Invalid duration or end time is given for a stop%.", errorSuffix));
     516           12 :         return false;
     517              :     }
     518        39244 :     if (triggers.size() > 0 && stop.speed > 0) {
     519            9 :         errorOutput->inform(TLF("Triggers and waypoints cannot be combined%.", errorSuffix));
     520            3 :         return false;
     521              :     }
     522        39241 :     stop.extension = attrs.getOptSUMOTimeReporting(SUMO_ATTR_EXTENSION, nullptr, ok, -1);
     523        39241 :     const bool defaultParking = (stop.triggered || stop.containerTriggered || stop.parkingarea != "");
     524        39241 :     stop.parking = attrs.getOpt<ParkingType>(SUMO_ATTR_PARKING, nullptr, ok, defaultParking ? ParkingType::OFFROAD : ParkingType::ONROAD);
     525        39241 :     if ((stop.parkingarea != "") && (stop.parking == ParkingType::ONROAD)) {
     526           21 :         WRITE_WARNINGF(TL("Stop at parkingArea overrides attribute 'parking' for stop%."), errorSuffix);
     527            7 :         stop.parking = ParkingType::OFFROAD;
     528              :     }
     529              : 
     530              :     // expected persons
     531        39241 :     const std::vector<std::string>& expected = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED, nullptr, ok);
     532              :     stop.awaitedPersons.insert(expected.begin(), expected.end());
     533        39241 :     if (stop.awaitedPersons.size() > 0) {
     534          242 :         stop.triggered = true;
     535          242 :         if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
     536          123 :             stop.parking = ParkingType::OFFROAD;
     537              :         }
     538              :     }
     539              : 
     540              :     // permitted transportables
     541        39241 :     const std::vector<std::string>& permitted = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_PERMITTED, nullptr, ok);
     542              :     stop.permitted.insert(permitted.begin(), permitted.end());
     543              : 
     544              :     // expected containers
     545        39241 :     const std::vector<std::string>& expectedContainers = attrs.getOpt<std::vector<std::string> >(SUMO_ATTR_EXPECTED_CONTAINERS, nullptr, ok);
     546              :     stop.awaitedContainers.insert(expectedContainers.begin(), expectedContainers.end());
     547        39241 :     if (stop.awaitedContainers.size() > 0) {
     548           77 :         stop.containerTriggered = true;
     549           77 :         if ((stop.parametersSet & STOP_PARKING_SET) == 0) {
     550           67 :             stop.parking = ParkingType::OFFROAD;
     551              :         }
     552              :     }
     553              :     // public transport trip id
     554        39241 :     stop.tripId = attrs.getOpt<std::string>(SUMO_ATTR_TRIP_ID, nullptr, ok, "");
     555        39241 :     stop.split = attrs.getOpt<std::string>(SUMO_ATTR_SPLIT, nullptr, ok, "");
     556        39241 :     stop.join = attrs.getOpt<std::string>(SUMO_ATTR_JOIN, nullptr, ok, "");
     557        39241 :     stop.line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, nullptr, ok, "");
     558              : 
     559        39241 :     const std::string idx = attrs.getOpt<std::string>(SUMO_ATTR_INDEX, nullptr, ok, "end");
     560        39241 :     if (idx == "end") {
     561        39025 :         stop.index = STOP_INDEX_END;
     562          216 :     } else if (idx == "fit") {
     563           14 :         stop.index = STOP_INDEX_FIT;
     564              :     } else {
     565          202 :         stop.index = attrs.get<int>(SUMO_ATTR_INDEX, nullptr, ok);
     566          202 :         if (!ok || stop.index < 0) {
     567           18 :             errorOutput->inform(TLF("Invalid 'index' for stop%.", errorSuffix));
     568            6 :             return false;
     569              :         }
     570              :     }
     571        39235 :     stop.started = attrs.getOptSUMOTimeReporting(SUMO_ATTR_STARTED, nullptr, ok, -1);
     572        39235 :     stop.ended = attrs.getOptSUMOTimeReporting(SUMO_ATTR_ENDED, nullptr, ok, -1);
     573        39235 :     stop.posLat = attrs.getOpt<double>(SUMO_ATTR_POSITION_LAT, nullptr, ok, INVALID_DOUBLE);
     574        39235 :     stop.actType = attrs.getOpt<std::string>(SUMO_ATTR_ACTTYPE, nullptr, ok, "");
     575        39235 :     stop.onDemand = attrs.getOpt<bool>(SUMO_ATTR_ONDEMAND, nullptr, ok, false);
     576        39235 :     stop.priority = attrs.getOpt<double>(SUMO_ATTR_PRIORITY, nullptr, ok, -1);
     577        39235 :     stop.jump = attrs.getOptSUMOTimeReporting(SUMO_ATTR_JUMP, nullptr, ok, -1);
     578        39235 :     stop.jumpUntil = attrs.getOptSUMOTimeReporting(SUMO_ATTR_JUMP_UNTIL, nullptr, ok, -1);
     579        39235 :     stop.collision = attrs.getOpt<bool>(SUMO_ATTR_COLLISION, nullptr, ok, false);
     580        39235 :     return true;
     581        39256 : }
     582              : 
     583              : 
     584              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1