LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSStageTrip.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.9 % 218 196
Test Date: 2024-12-21 15:45:41 Functions: 81.2 % 16 13

            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    MSStageTrip.cpp
      15              : /// @author  Melanie Weber
      16              : /// @author  Andreas Kendziorra
      17              : /// @author  Michael Behrisch
      18              : /// @author  Jakob Erdmann
      19              : /// @date    Wed, 1 Jun 2022
      20              : ///
      21              : // An intermodal routing request (to be transformed into a sequence of walks and rides)
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <utils/common/StringTokenizer.h>
      26              : #include <utils/geom/GeomHelper.h>
      27              : #include <utils/options/OptionsCont.h>
      28              : #include <utils/vehicle/SUMOVehicleParameter.h>
      29              : #include <utils/router/PedestrianRouter.h>
      30              : #include <utils/router/IntermodalRouter.h>
      31              : #include <microsim/MSEdge.h>
      32              : #include <microsim/MSLane.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSStoppingPlace.h>
      35              : #include <microsim/MSVehicleControl.h>
      36              : #include <microsim/transportables/MSStageDriving.h>
      37              : #include <microsim/transportables/MSStageWaiting.h>
      38              : #include <microsim/transportables/MSStageWalking.h>
      39              : #include <microsim/transportables/MSTransportable.h>
      40              : #include <microsim/transportables/MSPerson.h>
      41              : #include <microsim/transportables/MSStageTrip.h>
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // method definitions
      46              : // ===========================================================================
      47              : 
      48              : /* -------------------------------------------------------------------------
      49              : * MSStageTrip - methods
      50              : * ----------------------------------------------------------------------- */
      51       227676 : MSStageTrip::MSStageTrip(const MSEdge* origin, MSStoppingPlace* fromStop,
      52              :                          const MSEdge* destination, MSStoppingPlace* toStop,
      53              :                          const SUMOTime duration, const SVCPermissions modeSet,
      54              :                          const std::string& vTypes, const double speed, const double walkFactor,
      55              :                          const std::string& group,
      56       227676 :                          const double departPosLat, const bool hasArrivalPos, const double arrivalPos):
      57              :     MSStage(MSStageType::TRIP, destination, toStop, arrivalPos, 0.0, group),
      58       227676 :     myOrigin(origin),
      59       227676 :     myOriginStop(fromStop),
      60       227676 :     myDuration(duration),
      61       227676 :     myModeSet(modeSet),
      62       227676 :     myVTypes(vTypes),
      63       227676 :     mySpeed(speed),
      64       227676 :     myWalkFactor(walkFactor),
      65       227676 :     myDepartPosLat(departPosLat),
      66       227676 :     myHaveArrivalPos(hasArrivalPos) {
      67       227676 : }
      68              : 
      69              : 
      70       455340 : MSStageTrip::~MSStageTrip() {}
      71              : 
      72              : MSStage*
      73       219553 : MSStageTrip::clone() const {
      74       219553 :     MSStage* const clon = new MSStageTrip(myOrigin, const_cast<MSStoppingPlace*>(myOriginStop),
      75       219553 :                                           myDestination, myDestinationStop, myDuration,
      76       219553 :                                           myModeSet, myVTypes, mySpeed, myWalkFactor, myGroup,
      77       219553 :                                           myDepartPosLat, myHaveArrivalPos, myArrivalPos);
      78       219553 :     clon->setParameters(*this);
      79       219553 :     return clon;
      80              : }
      81              : 
      82              : 
      83              : Position
      84            0 : MSStageTrip::getPosition(SUMOTime /* now */) const {
      85              :     // may be called concurrently while the trip is still being routed
      86            0 :     return getEdgePosition(myOrigin, myDepartPos, ROADSIDE_OFFSET * (MSGlobals::gLefthand ? -1 : 1));
      87              : }
      88              : 
      89              : 
      90              : double
      91            0 : MSStageTrip::getAngle(SUMOTime /* now */) const {
      92              :     // may be called concurrently while the trip is still being routed
      93            0 :     return getEdgeAngle(myOrigin, myDepartPos) + M_PI / 2 * (MSGlobals::gLefthand ? -1 : 1);
      94              : }
      95              : 
      96              : 
      97              : const MSEdge*
      98       419080 : MSStageTrip::getEdge() const {
      99       419080 :     return myOrigin;
     100              : }
     101              : 
     102              : 
     103              : double
     104       410708 : MSStageTrip::getEdgePos(SUMOTime /* now */) const {
     105       410708 :     return myDepartPos;
     106              : }
     107              : 
     108              : 
     109              : std::vector<SUMOVehicle*>
     110       206704 : MSStageTrip::getVehicles(MSVehicleControl& vehControl, MSTransportable* transportable, const MSEdge* origin) {
     111              :     std::vector<SUMOVehicleParameter*> pars;
     112       413515 :     for (StringTokenizer st(myVTypes); st.hasNext();) {
     113          107 :         pars.push_back(new SUMOVehicleParameter());
     114          214 :         pars.back()->vtypeid = st.next();
     115          107 :         pars.back()->parametersSet |= VEHPARS_VTYPE_SET;
     116          107 :         pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     117          214 :         pars.back()->id = transportable->getID() + "_" + toString(pars.size() - 1);
     118       206704 :     }
     119       206704 :     if (pars.empty()) {
     120       206601 :         if ((myModeSet & SVC_PASSENGER) != 0) {
     121         1572 :             pars.push_back(new SUMOVehicleParameter());
     122         3144 :             pars.back()->id = transportable->getID() + "_0";
     123         1572 :             pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     124              :         }
     125       206601 :         if ((myModeSet & SVC_TAXI) != 0) {
     126          135 :             pars.push_back(new SUMOVehicleParameter());
     127          135 :             pars.back()->vtypeid = DEFAULT_TAXITYPE_ID;
     128          270 :             pars.back()->id = transportable->getID() + "_taxi";
     129          135 :             pars.back()->line = "taxi";
     130              :         }
     131       206601 :         if ((myModeSet & SVC_BICYCLE) != 0) {
     132           37 :             pars.push_back(new SUMOVehicleParameter());
     133           37 :             pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
     134           74 :             pars.back()->id = transportable->getID() + "_b0";
     135           37 :             pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     136              :         }
     137              :     }
     138       413408 :     ConstMSRoutePtr const routeDummy = std::make_shared<MSRoute>(transportable->getID() + "_0", ConstMSEdgeVector({ origin }), false, nullptr, std::vector<SUMOVehicleParameter::Stop>());
     139              :     std::vector<SUMOVehicle*> result;
     140       208555 :     for (SUMOVehicleParameter* vehPar : pars) {
     141         1851 :         const bool isTaxi = vehPar->vtypeid == DEFAULT_TAXITYPE_ID && vehPar->line == "taxi";
     142         1851 :         if (myDepartPos != 0) {
     143           76 :             vehPar->departPosProcedure = DepartPosDefinition::GIVEN;
     144           76 :             vehPar->departPos = myDepartPos;
     145           76 :             vehPar->parametersSet |= VEHPARS_DEPARTPOS_SET;
     146              :         }
     147         1851 :         vehPar->parametersSet |= VEHPARS_ARRIVALPOS_SET;
     148         1851 :         vehPar->arrivalPosProcedure = ArrivalPosDefinition::GIVEN;
     149         1851 :         vehPar->parametersSet |= VEHPARS_ARRIVALSPEED_SET;
     150         1851 :         vehPar->arrivalSpeedProcedure = ArrivalSpeedDefinition::GIVEN;
     151         1851 :         vehPar->arrivalSpeed = 0;
     152         1851 :         MSVehicleType* type = vehControl.getVType(vehPar->vtypeid);
     153         1851 :         if (type->getVehicleClass() != SVC_IGNORING && (origin->getPermissions() & type->getVehicleClass()) == 0 && !isTaxi) {
     154          120 :             WRITE_WARNINGF(TL("Ignoring vehicle type '%' when routing person '%' because it is not allowed on the start edge."), type->getID(), transportable->getID());
     155           40 :             delete vehPar;
     156              :         } else {
     157         3622 :             result.push_back(vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes));
     158              :         }
     159              :     }
     160       206704 :     if (result.empty()) {
     161              :         // walking only but may use access infrastructure
     162       204927 :         result.push_back(nullptr);
     163              :     }
     164       206704 :     return result;
     165       206704 : }
     166              : 
     167              : 
     168              : const std::string
     169       206704 : MSStageTrip::reroute(const SUMOTime time, MSTransportableRouter& router, MSTransportable* const transportable,
     170              :                      MSStage* previous, const MSEdge* origin, const MSEdge* destination, std::vector<MSStage*>& stages) {
     171       206704 :     if (origin->isTazConnector() && origin->getSuccessors().size() == 0) {
     172              :         // previous stage ended at a taz sink-edge
     173          299 :         origin = transportable->getNextStage(-1)->getDestination();
     174              :     }
     175       206704 :     MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl();
     176              :     double minCost = std::numeric_limits<double>::max();
     177              :     std::vector<MSTransportableRouter::TripItem> minResult;
     178              :     SUMOVehicle* minVehicle = nullptr;
     179       413442 :     for (SUMOVehicle* vehicle : getVehicles(vehControl, transportable, origin)) {
     180              :         std::vector<MSTransportableRouter::TripItem> result;
     181       206738 :         double departPos = previous->getArrivalPos();
     182              :         MSStoppingPlace* const prevStop = previous->getDestinationStop();
     183       206738 :         if (MSGlobals::gUseMesoSim && prevStop != nullptr) {
     184          190 :             departPos = (prevStop->getBeginLanePosition() + prevStop->getEndLanePosition()) / 2.;
     185              :         }
     186       432630 :         if (router.compute(origin, destination, departPos, prevStop == nullptr ? "" : prevStop->getID(),
     187       383071 :                            myArrivalPos, myDestinationStop == nullptr ? "" : myDestinationStop->getID(),
     188       206738 :                            transportable->getMaxSpeed() * myWalkFactor, vehicle, myModeSet, time, result)) {
     189              :             double totalCost = 0;
     190       438327 :             for (const MSTransportableRouter::TripItem& item : result) {
     191       231652 :                 totalCost += item.cost;
     192              :             }
     193       206675 :             if (totalCost < minCost) {
     194              :                 minCost = totalCost;
     195              :                 minResult.swap(result);
     196              :                 std::swap(minVehicle, vehicle);
     197              :             }
     198              :         }
     199       206738 :         if (vehicle != nullptr) {
     200           41 :             vehControl.deleteVehicle(vehicle, true);
     201              :         }
     202       413442 :     }
     203       206704 :     if (minCost != std::numeric_limits<double>::max()) {
     204       206641 :         const bool isTaxi = minVehicle != nullptr && minVehicle->getParameter().vtypeid == DEFAULT_TAXITYPE_ID && minVehicle->getParameter().line == "taxi";
     205              :         bool carUsed = false;
     206       438247 :         for (std::vector<MSTransportableRouter::TripItem>::iterator it = minResult.begin(); it != minResult.end(); ++it) {
     207       231606 :             if (!it->edges.empty()) {
     208       212459 :                 MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(it->destStop, SUMO_TAG_BUS_STOP);
     209       212459 :                 double localArrivalPos = bs != nullptr ? bs->getAccessPos(it->edges.back()) : it->edges.back()->getLength() / 2.;
     210       212459 :                 const MSEdge* const first = it->edges.front();
     211       212459 :                 const MSEdge* const rideOrigin = origin->isTazConnector() && stages.empty() ? first : nullptr;
     212       212459 :                 if (it + 1 == minResult.end() && myHaveArrivalPos) {
     213         5561 :                     localArrivalPos = myArrivalPos;
     214              :                 }
     215       212459 :                 if (it->line == "") {
     216              :                     // determine walk departPos
     217       207913 :                     double depPos = previous->getArrivalPos();
     218       207913 :                     if (previous->getDestinationStop() != nullptr) {
     219        21948 :                         depPos = previous->getDestinationStop()->getAccessPos(first, first->getLanes()[0]->getRNG());
     220       185965 :                     } else if (origin->isTazConnector()) {
     221              :                         // walk the whole length of the first edge
     222          105 :                         if (std::find(first->getPredecessors().begin(), first->getPredecessors().end(), origin) != first->getPredecessors().end()) {
     223              :                             depPos = 0;
     224              :                         } else {
     225              :                             depPos = first->getLength();
     226              :                         }
     227       185860 :                     } else if (previous->getDestination() != first) {
     228           53 :                         if ((previous->getDestination()->getToJunction() == first->getToJunction())
     229           53 :                                 || (previous->getDestination()->getFromJunction() == first->getToJunction())) {
     230              :                             depPos = first->getLength();
     231              :                         } else {
     232              :                             depPos = 0.;
     233              :                         }
     234              :                     }
     235       207913 :                     if (destination->isTazConnector()) {
     236              :                         // walk the whole length of the last edge
     237          745 :                         const MSEdge* last = it->edges.back();
     238          745 :                         if (std::find(last->getSuccessors().begin(), last->getSuccessors().end(), destination) != last->getSuccessors().end()) {
     239              :                             localArrivalPos = last->getLength();
     240              :                         } else {
     241              :                             localArrivalPos = 0;
     242              :                         }
     243              :                     }
     244       207913 :                     previous = new MSStageWalking(transportable->getID(), it->edges, bs, myDuration, mySpeed, depPos, localArrivalPos, myDepartPosLat);
     245       207913 :                     previous->setParameters(*this);
     246       207913 :                     previous->setCosts(it->cost);
     247              :                     previous->setTrip(this);
     248       207913 :                     stages.push_back(previous);
     249         4546 :                 } else if (isTaxi) {
     250          117 :                     const ConstMSEdgeVector& prevEdges = previous->getEdges();
     251          117 :                     if (prevEdges.size() >= 2 && previous->getDestinationStop() == nullptr) {
     252              :                         // determine walking direction and let the previous
     253              :                         // stage end after entering its final edge
     254            6 :                         const MSEdge* last = prevEdges.back();
     255            6 :                         const MSEdge* prev = prevEdges[prevEdges.size() - 2];
     256            6 :                         if (last->getFromJunction() == prev->getToJunction() || prev->getFromJunction() == last->getFromJunction()) {
     257              :                             previous->setArrivalPos(MIN2(last->getLength(), 10.0));
     258              :                         } else {
     259            6 :                             previous->setArrivalPos(MAX2(0.0, last->getLength() - 10));
     260              :                         }
     261              :                     }
     262          351 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ "taxi" }), myGroup);
     263          117 :                     previous->setParameters(*this);
     264          117 :                     previous->setCosts(it->cost);
     265              :                     previous->setTrip(this);
     266          117 :                     stages.push_back(previous);
     267         4546 :                 } else if (minVehicle != nullptr && it->line == minVehicle->getID()) {
     268         1507 :                     if (bs == nullptr && it + 1 != minResult.end()) {
     269              :                         // we have no defined endpoint and are in the middle of the trip, drive as far as possible
     270           49 :                         localArrivalPos = it->edges.back()->getLength();
     271              :                     }
     272         4521 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ it->line }));
     273         1507 :                     previous->setParameters(*this);
     274         1507 :                     previous->setCosts(it->cost);
     275              :                     previous->setTrip(this);
     276         1507 :                     stages.push_back(previous);
     277         1507 :                     minVehicle->replaceRouteEdges(it->edges, -1, 0, "person:" + transportable->getID(), true);
     278         1507 :                     minVehicle->setArrivalPos(localArrivalPos);
     279         1507 :                     const_cast<SUMOVehicleParameter&>(minVehicle->getParameter()).arrivalPos = localArrivalPos;
     280         1507 :                     vehControl.addVehicle(minVehicle->getID(), minVehicle);
     281              :                     carUsed = true;
     282              :                 } else {
     283         8766 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ it->line }), myGroup, it->intended, TIME2STEPS(it->depart));
     284         2922 :                     previous->setParameters(*this);
     285         2922 :                     previous->setCosts(it->cost);
     286              :                     previous->setTrip(this);
     287         2922 :                     stages.push_back(previous);
     288              :                 }
     289              :             }
     290              :         }
     291       206641 :         if (wasSet(VEHPARS_ARRIVALPOS_SET) && !stages.empty()) {
     292              :             // mark the last stage
     293         1175 :             stages.back()->markSet(VEHPARS_ARRIVALPOS_SET);
     294              :         }
     295              :         setCosts(minCost);
     296       206641 :         if (minVehicle != nullptr && (isTaxi || !carUsed)) {
     297          263 :             vehControl.deleteVehicle(minVehicle, true);
     298              :         }
     299              :     } else {
     300              :         // append stage so the GUI won't crash due to inconsistent state
     301           63 :         previous = new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat);
     302           63 :         previous->setParameters(*this);
     303           63 :         stages.push_back(previous);
     304           63 :         if (MSGlobals::gCheckRoutes) {  // if not pedestrians will teleport
     305          117 :             return "No connection found between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
     306              :         }
     307              :     }
     308       206665 :     if (stages.empty()) {
     309              :         // append stage so the GUI won't crash due to inconsistent state
     310           14 :         if (myOriginStop != nullptr && myOriginStop == myDestinationStop) {
     311           28 :             stages.push_back(new MSStageWaiting(destination, myDestinationStop, 0, -1, previous->getArrivalPos(), "sameStop", false));
     312              :         } else {
     313            0 :             stages.push_back(new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat));
     314            0 :             if (MSGlobals::gCheckRoutes) {  // if not pedestrians will teleport
     315            0 :                 return "Empty route between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
     316              :             }
     317              :         }
     318              :     }
     319       206665 :     return "";
     320       206938 : }
     321              : 
     322              : 
     323              : const std::string
     324       206624 : MSStageTrip::setArrived(MSNet* net, MSTransportable* transportable, SUMOTime now, const bool vehicleArrived) {
     325       413248 :     MSStage::setArrived(net, transportable, now, vehicleArrived);
     326              :     std::vector<MSStage*> stages;
     327              :     std::string result;
     328       206624 :     if (transportable->getCurrentStageIndex() == 0) {
     329            0 :         myDepartPos = transportable->getParameter().departPos;
     330            0 :         if (transportable->getParameter().departPosProcedure == DepartPosDefinition::RANDOM) {
     331              :             // TODO we should probably use the rng of the lane here
     332            0 :             myDepartPos = RandHelper::rand(myOrigin->getLength());
     333              :         }
     334            0 :         MSStageWaiting start(myOrigin, myOriginStop, -1, transportable->getParameter().depart, myDepartPos, "start", true);
     335            0 :         result = reroute(transportable->getParameter().depart, net->getIntermodalRouter(0), transportable, &start, myOrigin, myDestination, stages);
     336            0 :     } else {
     337              :         MSStage* previous = transportable->getNextStage(-1);
     338       206624 :         myDepartPos = previous->getArrivalPos();
     339       413248 :         result = reroute(now, net->getIntermodalRouter(0), transportable, previous, myOrigin, myDestination, stages);
     340              :     }
     341              :     int idx = 1;
     342       419036 :     for (MSStage* stage : stages) {
     343       212412 :         transportable->appendStage(stage, idx++);
     344              :     }
     345       206624 :     return result;
     346       206624 : }
     347              : 
     348              : 
     349              : void
     350       206624 : MSStageTrip::proceed(MSNet* net, MSTransportable* transportable, SUMOTime now, MSStage* /* previous */) {
     351              :     // just skip the stage, every interesting happens in setArrived
     352       206624 :     transportable->proceed(net, now);
     353       206585 : }
     354              : 
     355              : 
     356              : std::string
     357           39 : MSStageTrip::getOriginDescription() const {
     358           39 :     return (myOriginStop != nullptr
     359           85 :             ? toString(myOriginStop->getElement()) + " '" + myOriginStop->getID()
     360           71 :             : "edge '" + myOrigin->getID()) + "'";
     361              : }
     362              : 
     363              : std::string
     364           39 : MSStageTrip::getDestinationDescription() const {
     365           39 :     return (myDestinationStop != nullptr
     366           85 :             ? toString(myDestinationStop->getElement()) + " '" + myDestinationStop->getID()
     367           71 :             : "edge '" + myDestination->getID()) + "'";
     368              : }
     369              : 
     370              : std::string
     371            0 : MSStageTrip::getStageSummary(const bool) const {
     372            0 :     return "trip from " + getOriginDescription() + " to " + getDestinationDescription();
     373              : }
     374              : 
     375              : void
     376         1427 : MSStageTrip::routeOutput(const bool /*isPerson*/, OutputDevice& os, const bool /*withRouteLength*/, const MSStage* const previous) const {
     377         1427 :     if (myArrived < 0) {
     378           10 :         const bool walkFactorSet = myWalkFactor != OptionsCont::getOptions().getFloat("persontrip.walkfactor");
     379           10 :         const bool groupSet = myGroup != OptionsCont::getOptions().getString("persontrip.default.group");
     380              :         // could still be a persontrip but most likely it was a walk in the input
     381           10 :         SumoXMLTag tag = myModeSet == 0 && !walkFactorSet && !groupSet ? SUMO_TAG_WALK : SUMO_TAG_PERSONTRIP;
     382           10 :         os.openTag(tag);
     383           10 :         if (previous == nullptr || previous->getStageType() == MSStageType::WAITING_FOR_DEPART) {
     384            4 :             os.writeAttr(SUMO_ATTR_FROM, myOrigin->getID());
     385              :         }
     386           10 :         if (myDestinationStop == nullptr) {
     387           10 :             os.writeAttr(SUMO_ATTR_TO, myDestination->getID());
     388           10 :             if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
     389            6 :                 os.writeAttr(SUMO_ATTR_ARRIVALPOS, myArrivalPos);
     390              :             }
     391              :         } else {
     392            0 :             os.writeAttr(toString(myDestinationStop->getElement()), myDestinationStop->getID());
     393              :         }
     394              :         std::vector<std::string> modes;
     395           10 :         if ((myModeSet & SVC_PASSENGER) != 0) {
     396            4 :             modes.push_back("car");
     397              :         }
     398           10 :         if ((myModeSet & SVC_BICYCLE) != 0) {
     399            0 :             modes.push_back("bicycle");
     400              :         }
     401           10 :         if ((myModeSet & SVC_TAXI) != 0) {
     402            0 :             modes.push_back("taxi");
     403              :         }
     404           10 :         if ((myModeSet & SVC_BUS) != 0) {
     405            0 :             modes.push_back("public");
     406              :         }
     407           10 :         if (modes.size() > 0) {
     408              :             os.writeAttr(SUMO_ATTR_MODES, modes);
     409              :         }
     410           10 :         if (myVTypes.size() > 0) {
     411            0 :             os.writeAttr(SUMO_ATTR_VTYPES, myVTypes);
     412              :         }
     413           10 :         if (groupSet) {
     414              :             os.writeAttr(SUMO_ATTR_GROUP, myGroup);
     415              :         }
     416           10 :         if (walkFactorSet) {
     417            0 :             os.writeAttr(SUMO_ATTR_WALKFACTOR, myWalkFactor);
     418              :         }
     419           20 :         if (OptionsCont::getOptions().getBool("vehroute-output.cost")) {
     420            0 :             os.writeAttr(SUMO_ATTR_COST, getCosts());
     421              :         }
     422           10 :         os.closeTag();
     423           10 :     }
     424         1427 : }
     425              : 
     426              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1