LCOV - code coverage report
Current view: top level - src/duarouter - duarouter_main.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 84.2 % 133 112
Test Date: 2025-12-06 15:35:27 Functions: 100.0 % 3 3

            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    duarouter_main.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Thu, 06 Jun 2002
      19              : ///
      20              : // Main for DUAROUTER
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #ifdef HAVE_VERSION_H
      25              : #include <version.h>
      26              : #endif
      27              : 
      28              : #include <iostream>
      29              : #include <string>
      30              : #include <limits.h>
      31              : #include <ctime>
      32              : #include <memory>
      33              : #include <xercesc/sax/SAXException.hpp>
      34              : #include <xercesc/sax/SAXParseException.hpp>
      35              : #include <utils/common/StringUtils.h>
      36              : #include <utils/common/MsgHandler.h>
      37              : #include <utils/common/UtilExceptions.h>
      38              : #include <utils/common/SystemFrame.h>
      39              : #include <utils/common/RandHelper.h>
      40              : #include <utils/common/ToString.h>
      41              : #include <utils/vehicle/SUMORouteHandler.h>
      42              : #ifdef HAVE_FOX
      43              : #include <utils/foxtools/MsgHandlerSynchronized.h>
      44              : #endif
      45              : #include <utils/iodevices/OutputDevice.h>
      46              : #include <utils/options/Option.h>
      47              : #include <utils/options/OptionsCont.h>
      48              : #include <utils/options/OptionsIO.h>
      49              : #include <utils/router/DijkstraRouter.h>
      50              : #include <utils/router/AFRouter.h>
      51              : #include <utils/router/AStarRouter.h>
      52              : #include <utils/router/CHRouter.h>
      53              : #include <utils/router/CHRouterWrapper.h>
      54              : #include <utils/vehicle/SUMOVehicleParserHelper.h>
      55              : #include <utils/xml/XMLSubSys.h>
      56              : #include <router/ROFrame.h>
      57              : #include <router/ROLoader.h>
      58              : #include <router/RONet.h>
      59              : #include <router/ROEdge.h>
      60              : #include "RODUAEdgeBuilder.h"
      61              : #include "RODUAFrame.h"
      62              : 
      63              : 
      64              : // ===========================================================================
      65              : // functions
      66              : // ===========================================================================
      67              : /* -------------------------------------------------------------------------
      68              :  * data processing methods
      69              :  * ----------------------------------------------------------------------- */
      70              : /**
      71              :  * loads the net
      72              :  * The net is in this meaning made up by the net itself and the dynamic
      73              :  * weights which may be supplied in a separate file
      74              :  */
      75              : void
      76         3343 : initNet(RONet& net, ROLoader& loader, OptionsCont& oc) {
      77              :     // load the net
      78         3343 :     RODUAEdgeBuilder builder;
      79         3343 :     ROEdge::setGlobalOptions(oc.getBool("weights.interpolate"));
      80         3343 :     loader.loadNet(net, builder);
      81              :     // load the weights when wished/available
      82         6194 :     if (oc.isSet("weight-files")) {
      83         1263 :         loader.loadWeights(net, "weight-files", oc.getString("weight-attribute"), false, oc.getBool("weights.expand"));
      84              :     }
      85         6194 :     if (oc.isSet("lane-weight-files")) {
      86            6 :         loader.loadWeights(net, "lane-weight-files", oc.getString("weight-attribute"), true, oc.getBool("weights.expand"));
      87              :     }
      88         6194 :     if (oc.getBool("skip-new-routes")) {
      89              :         RORouteDef::setSkipNew();
      90              :     }
      91         3343 : }
      92              : 
      93              : 
      94              : /**
      95              :  * Computes the routes saving them
      96              :  */
      97              : void
      98         3097 : computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
      99              :     // initialise the loader
     100         3097 :     loader.openRoutes(net);
     101              :     // build the router
     102         2656 :     auto ttFunction = gWeightsRandomFactor > 1 ? &ROEdge::getTravelTimeStaticRandomized : &ROEdge::getTravelTimeStatic;
     103              :     SUMOAbstractRouter<ROEdge, ROVehicle>* router;
     104         2656 :     const std::string measure = oc.getString("weight-attribute");
     105         2710 :     const std::string routingAlgorithm = oc.getString("routing-algorithm");
     106         2656 :     const double priorityFactor = oc.getFloat("weights.priority-factor");
     107         2656 :     const SUMOTime begin = string2time(oc.getString("begin"));
     108         3156 :     const SUMOTime end = oc.isDefault("end") ? SUMOTime_MAX : string2time(oc.getString("end"));
     109              :     DijkstraRouter<ROEdge, ROVehicle>::Operation op = &ROEdge::getTravelTimeStatic;
     110              : 
     111         5312 :     if (oc.isSet("restriction-params") &&
     112           24 :             (routingAlgorithm == "CH" || routingAlgorithm == "CHWrapper")) {
     113           36 :         throw ProcessError(TLF("Routing algorithm '%' does not support restriction-params", routingAlgorithm));
     114              :     }
     115              : 
     116         2644 :     if (measure == "traveltime" && priorityFactor == 0) {
     117         2630 :         if (routingAlgorithm == "dijkstra") {
     118         2348 :             router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, nullptr, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
     119         1456 :         } else if (routingAlgorithm == "astar") {
     120              :             typedef AStarRouter<ROEdge, ROVehicle, ROMapMatcher> AStar;
     121          506 :             std::shared_ptr<const AStar::LookupTable> lookup;
     122         1012 :             if (oc.isSet("astar.all-distances")) {
     123            0 :                 lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)ROEdge::getAllEdges().size());
     124         1018 :             } else if (oc.isSet("astar.landmark-distances")) {
     125              :                 /* CHRouterWrapper<ROEdge, ROVehicle> chrouter(
     126              :                     ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic,
     127              :                     begin, end, SUMOTime_MAX, 1); */
     128           20 :                 DijkstraRouter<ROEdge, ROVehicle> forward(ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic);
     129              :                 std::vector<ReversedEdge<ROEdge, ROVehicle>*> reversed;
     130        33564 :                 for (ROEdge* edge : ROEdge::getAllEdges()) {
     131        33544 :                     reversed.push_back(edge->getReversedRoutingEdge());
     132              :                 }
     133        33564 :                 for (ReversedEdge<ROEdge, ROVehicle>* redge : reversed) {
     134        33544 :                     redge->init();
     135              :                 }
     136           20 :                 DijkstraRouter<ReversedEdge<ROEdge, ROVehicle>, ROVehicle> backward(reversed, true, &ReversedEdge<ROEdge, ROVehicle>::getTravelTimeStatic);
     137           26 :                 ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
     138           20 :                 ROMapMatcher* mapMatcher = dynamic_cast<ROMapMatcher*>(loader.getRouteHandler());
     139           40 :                 lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), ROEdge::getAllEdges(), &forward, &backward, &defaultVehicle,
     140           60 :                          oc.isSet("astar.save-landmark-distances") ? oc.getString("astar.save-landmark-distances") : "", oc.getInt("routing-threads"), mapMatcher);
     141           40 :             }
     142         1014 :             router = new AStar(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, lookup, net.hasPermissions(), oc.isSet("restriction-params"));
     143          950 :         } else if (routingAlgorithm == "CH" && !net.hasPermissions()) {
     144           79 :             const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
     145           97 :                                            string2time(oc.getString("weight-period")) :
     146              :                                            SUMOTime_MAX);
     147              :             router = new CHRouter<ROEdge, ROVehicle>(
     148          158 :                 ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, SVC_IGNORING, weightPeriod, net.hasPermissions(), oc.isSet("restriction-params"));
     149          871 :         } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
     150              :             // use CHWrapper instead of CH if the net has permissions
     151          871 :             const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
     152          897 :                                            string2time(oc.getString("weight-period")) :
     153              :                                            SUMOTime_MAX);
     154              :             router = new CHRouterWrapper<ROEdge, ROVehicle>(
     155         1742 :                 ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction,
     156         2613 :                 begin, end, weightPeriod, net.hasPermissions(), oc.getInt("routing-threads"));
     157            0 :         } else if (routingAlgorithm == "arcflag") {
     158              :             /// @brief The number of levels in the k-d tree partition
     159              :             constexpr auto NUMBER_OF_LEVELS = 5; //or 4 or 8
     160            0 :             ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
     161            0 :             KDTreePartition<ROEdge, RONode, ROVehicle>* partition = new KDTreePartition<ROEdge, RONode, ROVehicle>(NUMBER_OF_LEVELS, ROEdge::getAllEdges(), net.hasPermissions(), oc.isSet("restriction-params"));
     162            0 :             partition->init(&defaultVehicle);
     163            0 :             auto reversedTtFunction = gWeightsRandomFactor > 1 ? &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStaticRandomized : &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStatic;
     164            0 :             router = new AFRouter<ROEdge, RONode, ROVehicle, ROMapMatcher>(ROEdge::getAllEdges(),
     165            0 :                     partition, oc.getBool("ignore-errors"), ttFunction, reversedTtFunction, (oc.isSet("weight-files") ? string2time(oc.getString("weight-period")) : SUMOTime_MAX),
     166            0 :                     nullptr, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
     167            0 :         } else {
     168            0 :             throw ProcessError(TLF("Unknown routing Algorithm '%'!", routingAlgorithm));
     169              :         }
     170              :     } else {
     171           14 :         if (measure == "traveltime") {
     172            3 :             if (ROEdge::initPriorityFactor(priorityFactor)) {
     173              :                 op = &ROEdge::getTravelTimeStaticPriorityFactor;
     174              :             }
     175           11 :         } else if (measure == "CO") {
     176              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::CO>;
     177            8 :         } else if (measure == "CO2") {
     178              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::CO2>;
     179            7 :         } else if (measure == "PMx") {
     180              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::PM_X>;
     181            6 :         } else if (measure == "HC") {
     182              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::HC>;
     183            4 :         } else if (measure == "NOx") {
     184              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::NO_X>;
     185            3 :         } else if (measure == "fuel") {
     186              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::FUEL>;
     187            2 :         } else if (measure == "electricity") {
     188              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::ELEC>;
     189            2 :         } else if (measure == "noise") {
     190              :             op = &ROEdge::getNoiseEffort;
     191              :         } else {
     192              :             op = &ROEdge::getStoredEffort;
     193              :         }
     194           14 :         if (measure != "traveltime" && !net.hasLoadedEffort()) {
     195            6 :             WRITE_WARNINGF(TL("No weight data was loaded for attribute '%'."), measure);
     196              :         }
     197              :         router = new DijkstraRouter<ROEdge, ROVehicle>(
     198           28 :             ROEdge::getAllEdges(), oc.getBool("ignore-errors"), op, ttFunction, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
     199              :     }
     200         2638 :     const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, true);
     201         5330 :     double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
     202              : 
     203              :     RailwayRouter<ROEdge, ROVehicle>* railRouter = nullptr;
     204         2638 :     if (net.hasBidiEdges()) {
     205          126 :         railRouter = new RailwayRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), true, op, ttFunction, false, net.hasPermissions(),
     206          126 :                 oc.isSet("restriction-params"),
     207              :                 oc.getFloat("railway.max-train-length"),
     208          189 :                 oc.getFloat("weights.reversal-penalty"));
     209              :     }
     210         2638 :     RORouterProvider provider(router, new PedestrianRouter<ROEdge, ROLane, RONode, ROVehicle>(),
     211         2638 :                               new ROIntermodalRouter(RONet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm),
     212              :                               railRouter);
     213              :     // process route definitions
     214              :     try {
     215         2638 :         net.openOutput(oc);
     216         5236 :         loader.processRoutes(begin, end, string2time(oc.getString("route-steps")), net, provider);
     217         2602 :         net.writeIntermodal(oc, provider.getIntermodalRouter());
     218              :         // end the processing
     219         2602 :         net.cleanup();
     220           36 :     } catch (ProcessError&) {
     221           36 :         net.cleanup();
     222           36 :         throw;
     223           36 :     }
     224         5240 : }
     225              : 
     226              : 
     227              : /* -------------------------------------------------------------------------
     228              :  * main
     229              :  * ----------------------------------------------------------------------- */
     230              : int
     231         3649 : main(int argc, char** argv) {
     232         3649 :     OptionsCont& oc = OptionsCont::getOptions();
     233         3649 :     oc.setApplicationDescription(TL("Shortest path router and DUE computer for the microscopic, multi-modal traffic simulation SUMO."));
     234         7298 :     oc.setApplicationName("duarouter", "Eclipse SUMO duarouter " VERSION_STRING);
     235              :     int ret = 0;
     236              :     RONet* net = nullptr;
     237              :     try {
     238         3649 :         XMLSubSys::init();
     239         3649 :         RODUAFrame::fillOptions();
     240         3649 :         OptionsIO::setArgs(argc, argv);
     241         3649 :         OptionsIO::getOptions();
     242         3645 :         if (oc.processMetaOptions(argc < 2)) {
     243          255 :             SystemFrame::close();
     244          255 :             return 0;
     245              :         }
     246         3390 :         SystemFrame::checkOptions(oc);
     247        10170 :         XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
     248              : #ifdef HAVE_FOX
     249         6780 :         if (oc.getInt("routing-threads") > 1) {
     250              :             // make the output aware of threading
     251              :             MsgHandler::setFactory(&MsgHandlerSynchronized::create);
     252              :         }
     253              : #endif
     254         3390 :         MsgHandler::initOutputOptions();
     255         3390 :         if (!RODUAFrame::checkOptions()) {
     256           47 :             throw ProcessError();
     257              :         }
     258         3343 :         RandHelper::initRandGlobal();
     259              :         // load data
     260         4312 :         ROLoader loader(oc, false, !oc.getBool("no-step-log"));
     261         3343 :         net = new RONet();
     262         3343 :         initNet(*net, loader, oc);
     263              :         // build routes
     264              :         try {
     265         3097 :             computeRoutes(*net, loader, oc);
     266          495 :         } catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
     267            0 :             WRITE_ERROR(toString(e.getLineNumber()));
     268              :             ret = 1;
     269            0 :         } catch (XERCES_CPP_NAMESPACE::SAXException& e) {
     270            0 :             WRITE_ERROR(StringUtils::transcode(e.getMessage()));
     271              :             ret = 1;
     272            0 :         }
     273         2602 :         if (MsgHandler::getErrorInstance()->wasInformed() || ret != 0) {
     274          177 :             throw ProcessError();
     275              :         }
     276         4312 :     } catch (const ProcessError& e) {
     277         1891 :         if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
     278          862 :             WRITE_ERROR(e.what());
     279              :         }
     280          969 :         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
     281              :         ret = 1;
     282              : #ifndef _DEBUG
     283          969 :     } catch (const std::exception& e) {
     284            0 :         if (std::string(e.what()) != std::string("")) {
     285            0 :             WRITE_ERROR(e.what());
     286              :         }
     287            0 :         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
     288              :         ret = 1;
     289            0 :     } catch (...) {
     290            0 :         MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
     291              :         ret = 1;
     292              : #endif
     293            0 :     }
     294         3394 :     delete net;
     295         3394 :     SystemFrame::close();
     296         3394 :     if (ret == 0) {
     297              :         std::cout << "Success." << std::endl;
     298              :     }
     299              :     return ret;
     300              : }
     301              : 
     302              : 
     303              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1