LCOV - code coverage report
Current view: top level - src - od2trips_main.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.3 % 178 166
Test Date: 2026-07-05 15:55:58 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) 2002-2026 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    od2trips_main.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Laura Bieker
      19              : /// @author  Yun-Pang Floetteroed
      20              : /// @date    Thu, 12 September 2002
      21              : ///
      22              : // Main for OD2TRIPS
      23              : /****************************************************************************/
      24              : #include <config.h>
      25              : 
      26              : #ifdef HAVE_VERSION_H
      27              : #include <version.h>
      28              : #endif
      29              : 
      30              : #include <iostream>
      31              : #include <algorithm>
      32              : #include <cmath>
      33              : #include <cstdlib>
      34              : #include <string>
      35              : #include <utils/options/Option.h>
      36              : #include <utils/options/OptionsCont.h>
      37              : #include <utils/options/OptionsIO.h>
      38              : #include <utils/common/MsgHandler.h>
      39              : #include <utils/common/UtilExceptions.h>
      40              : #include <utils/common/SystemFrame.h>
      41              : #include <utils/common/RandHelper.h>
      42              : #include <utils/common/ToString.h>
      43              : #include <utils/xml/XMLSubSys.h>
      44              : #include <utils/common/StringUtils.h>
      45              : #include <od/ODDistrictCont.h>
      46              : #include <od/ODDistrictHandler.h>
      47              : #include <od/ODMatrix.h>
      48              : #include <utils/common/StringUtils.h>
      49              : #include <utils/common/SUMOTime.h>
      50              : #include <utils/common/StringTokenizer.h>
      51              : #include <utils/common/FileHelpers.h>
      52              : #include <utils/vehicle/SUMOVehicleParameter.h>
      53              : #include <utils/importio/LineReader.h>
      54              : #include <utils/iodevices/OutputDevice.h>
      55              : 
      56              : 
      57              : // ===========================================================================
      58              : // functions
      59              : // ===========================================================================
      60              : void
      61          160 : fillOptions() {
      62          160 :     OptionsCont& oc = OptionsCont::getOptions();
      63          320 :     oc.addCallExample("-c <CONFIGURATION>", TL("run with configuration file"));
      64              : 
      65              :     // insert options sub-topics
      66          160 :     SystemFrame::addConfigurationOptions(oc); // fill this subtopic, too
      67          160 :     oc.addOptionSubTopic("Input");
      68          160 :     oc.addOptionSubTopic("Output");
      69          160 :     oc.addOptionSubTopic("Time");
      70          160 :     oc.addOptionSubTopic("Processing");
      71          160 :     oc.addOptionSubTopic("Defaults");
      72          160 :     SystemFrame::addReportOptions(oc); // fill this subtopic, too
      73              : 
      74              : 
      75              :     // register the file input options
      76          160 :     oc.doRegister("taz-files", 'n', new Option_FileName());
      77          320 :     oc.addSynonyme("taz-files", "taz");
      78          320 :     oc.addSynonyme("taz-files", "net-file");
      79          320 :     oc.addSynonyme("taz-files", "net");
      80          320 :     oc.addDescription("taz-files", "Input", TL("Loads TAZ (districts; also from networks) from FILE(s)"));
      81              : 
      82          160 :     oc.doRegister("od-matrix-files", 'd', new Option_FileName());
      83          320 :     oc.addSynonyme("od-matrix-files", "od-files");
      84          320 :     oc.addSynonyme("od-matrix-files", "od");
      85          320 :     oc.addDescription("od-matrix-files", "Input", TL("Loads O/D-files from FILE(s)"));
      86              : 
      87          160 :     oc.doRegister("od-amitran-files", new Option_FileName());
      88          320 :     oc.addSynonyme("od-amitran-files", "amitran-files");
      89          320 :     oc.addSynonyme("od-amitran-files", "amitran");
      90          320 :     oc.addDescription("od-amitran-files", "Input", TL("Loads O/D-matrix in Amitran format from FILE(s)"));
      91              : 
      92          160 :     oc.doRegister("tazrelation-files", 'z', new Option_FileName());
      93          320 :     oc.addDescription("tazrelation-files", "Input", TL("Loads O/D-matrix in tazRelation format from FILE(s)"));
      94              : 
      95          320 :     oc.doRegister("tazrelation-attribute", new Option_String("count"));
      96          320 :     oc.addSynonyme("tazrelation-attribute", "attribute");
      97          320 :     oc.addDescription("tazrelation-attribute", "Input", TL("Define data attribute for loading counts (default 'count')"));
      98              : 
      99              :     // register the file output options
     100          160 :     oc.doRegister("output-file", 'o', new Option_FileName());
     101          320 :     oc.addSynonyme("output-file", "output", true);
     102          320 :     oc.addDescription("output-file", "Output", TL("Writes trip definitions into FILE"));
     103              : 
     104          160 :     oc.doRegister("flow-output", new Option_FileName());
     105          320 :     oc.addDescription("flow-output", "Output", TL("Writes flow definitions into FILE"));
     106              : 
     107          160 :     oc.doRegister("flow-output.probability", new Option_Bool(false));
     108          320 :     oc.addDescription("flow-output.probability", "Output", TL("Writes probabilistic flow instead of evenly spaced flow"));
     109              : 
     110          160 :     oc.doRegister("flow-output.poisson", new Option_Bool(false));
     111          320 :     oc.addDescription("flow-output.poisson", "Output", TL("Writes poisson distributed flow instead of evenly spaced flow"));
     112              : 
     113          160 :     oc.doRegister("pedestrians", new Option_Bool(false));
     114          320 :     oc.addDescription("pedestrians", "Output", TL("Writes pedestrians instead of vehicles"));
     115              : 
     116          160 :     oc.doRegister("persontrips", new Option_Bool(false));
     117          320 :     oc.addDescription("persontrips", "Output", TL("Writes persontrips instead of vehicles"));
     118              : 
     119          160 :     oc.doRegister("persontrips.modes", new Option_StringVector());
     120          320 :     oc.addDescription("persontrips.modes", "Output", TL("Add modes attribute to personTrips"));
     121              : 
     122          160 :     oc.doRegister("ignore-vehicle-type", new Option_Bool(false));
     123          320 :     oc.addSynonyme("ignore-vehicle-type", "no-vtype", true);
     124          320 :     oc.addDescription("ignore-vehicle-type", "Output", TL("Does not save vtype information"));
     125              : 
     126          160 :     oc.doRegister("junctions", new Option_Bool(false));
     127          320 :     oc.addDescription("junctions", "Output", TL("Writes trips between junctions"));
     128              : 
     129              : 
     130              :     // register the time settings
     131          320 :     oc.doRegister("begin", 'b', new Option_String("0", "TIME"));
     132          320 :     oc.addDescription("begin", "Time", TL("Defines the begin time; Previous trips will be discarded"));
     133              : 
     134          320 :     oc.doRegister("end", 'e', new Option_String("-1", "TIME"));
     135          320 :     oc.addDescription("end", "Time", TL("Defines the end time; Later trips will be discarded; Defaults to the maximum time that SUMO can represent"));
     136              : 
     137              : 
     138              :     // register the data processing options
     139          160 :     oc.doRegister("scale", 's', new Option_Float(1));
     140          320 :     oc.addDescription("scale", "Processing", TL("Scales the loaded flows by FLOAT"));
     141              : 
     142          160 :     oc.doRegister("spread.uniform", new Option_Bool(false));
     143          320 :     oc.addDescription("spread.uniform", "Processing", TL("Spreads trips uniformly over each time period"));
     144              : 
     145          160 :     oc.doRegister("different-source-sink", new Option_Bool(false));
     146          320 :     oc.addDescription("different-source-sink", "Processing", TL("Always choose source and sink edge which are not identical"));
     147              : 
     148          320 :     oc.doRegister("vtype", new Option_String(""));
     149          320 :     oc.addDescription("vtype", "Processing", TL("Defines the name of the vehicle type to use"));
     150              : 
     151          320 :     oc.doRegister("prefix", new Option_String(""));
     152          320 :     oc.addDescription("prefix", "Processing", TL("Defines the prefix for vehicle names"));
     153              : 
     154          160 :     oc.doRegister("timeline", new Option_StringVector());
     155          320 :     oc.addDescription("timeline", "Processing", TL("Uses STR[] as a timeline definition"));
     156              : 
     157          160 :     oc.doRegister("timeline.day-in-hours", new Option_Bool(false));
     158          320 :     oc.addDescription("timeline.day-in-hours", "Processing", TL("Uses STR as a 24h-timeline definition"));
     159              : 
     160          160 :     oc.doRegister("ignore-errors", new Option_Bool(false)); // !!! describe, document
     161          320 :     oc.addSynonyme("ignore-errors", "dismiss-loading-errors", true);
     162          320 :     oc.addDescription("ignore-errors", "Report", TL("Continue on broken input"));
     163              : 
     164          160 :     oc.doRegister("no-step-log", new Option_Bool(false));
     165          320 :     oc.addDescription("no-step-log", "Processing", TL("Disable console output of current time step"));
     166              : 
     167              : 
     168              :     // register defaults options
     169          320 :     oc.doRegister("departlane", new Option_String("free"));
     170          320 :     oc.addDescription("departlane", "Defaults", TL("Assigns a default depart lane"));
     171              : 
     172          160 :     oc.doRegister("departpos", new Option_String());
     173          320 :     oc.addDescription("departpos", "Defaults", TL("Assigns a default depart position"));
     174              : 
     175          320 :     oc.doRegister("departspeed", new Option_String("max"));
     176          320 :     oc.addDescription("departspeed", "Defaults", TL("Assigns a default depart speed"));
     177              : 
     178          160 :     oc.doRegister("arrivallane", new Option_String());
     179          320 :     oc.addDescription("arrivallane", "Defaults", TL("Assigns a default arrival lane"));
     180              : 
     181          160 :     oc.doRegister("arrivalpos", new Option_String());
     182          320 :     oc.addDescription("arrivalpos", "Defaults", TL("Assigns a default arrival position"));
     183              : 
     184          160 :     oc.doRegister("arrivalspeed", new Option_String());
     185          320 :     oc.addDescription("arrivalspeed", "Defaults", TL("Assigns a default arrival speed"));
     186              : 
     187              :     // add rand options
     188          160 :     RandHelper::insertRandOptions(oc);
     189          160 : }
     190              : 
     191              : bool
     192          154 : checkOptions() {
     193          154 :     OptionsCont& oc = OptionsCont::getOptions();
     194              :     bool ok = true;
     195          308 :     if (!oc.isSet("taz-files")) {
     196            2 :         WRITE_ERROR(TL("No TAZ input file (-n) specified."));
     197              :         ok = false;
     198              :     }
     199          197 :     if (!oc.isSet("od-matrix-files") && !oc.isSet("od-amitran-files") && !oc.isSet("tazrelation-files")) {
     200            4 :         WRITE_ERROR(TL("No input specified."));
     201              :         ok = false;
     202              :     }
     203          200 :     if (!oc.isSet("output-file") && !oc.isSet("flow-output")) {
     204            4 :         WRITE_ERROR(TL("No trip table output file (-o) or flow-output is specified."));
     205              :         ok = false;
     206              :     }
     207          160 :     if (oc.getBool("flow-output.probability") && oc.getBool("flow-output.poisson")) {
     208            0 :         WRITE_ERROR(TL("Only one of the options 'flow-output.probability' and 'flow-output.poisson' may be set."));
     209              :         ok = false;
     210              :     }
     211          162 :     if (oc.getBool("pedestrians") && oc.getBool("persontrips")) {
     212            0 :         WRITE_ERROR(TL("Only one of the Options 'pedestrians' and 'persontrips' may be set."));
     213              :         ok = false;
     214              :     }
     215              :     //
     216          154 :     SUMOVehicleParameter p;
     217              :     std::string error;
     218          923 :     if (oc.isSet("departlane") && !SUMOVehicleParameter::parseDepartLane(oc.getString("departlane"), "option", "departlane", p.departLane, p.departLaneProcedure, error)) {
     219            3 :         WRITE_ERROR(error);
     220              :         ok = false;
     221              :     }
     222          168 :     if (oc.isSet("departpos") && !SUMOVehicleParameter::parseDepartPos(oc.getString("departpos"), "option", "departpos", p.departPos, p.departPosProcedure, error)) {
     223            3 :         WRITE_ERROR(error);
     224              :         ok = false;
     225              :     }
     226          923 :     if (oc.isSet("departspeed") && !SUMOVehicleParameter::parseDepartSpeed(oc.getString("departspeed"), "option", "departspeed", p.departSpeed, p.departSpeedProcedure, error)) {
     227            3 :         WRITE_ERROR(error);
     228              :         ok = false;
     229              :     }
     230          163 :     if (oc.isSet("arrivallane") && !SUMOVehicleParameter::parseArrivalLane(oc.getString("arrivallane"), "option", "arrivallane", p.arrivalLane, p.arrivalLaneProcedure, error)) {
     231            3 :         WRITE_ERROR(error);
     232              :         ok = false;
     233              :     }
     234          168 :     if (oc.isSet("arrivalpos") && !SUMOVehicleParameter::parseArrivalPos(oc.getString("arrivalpos"), "option", "arrivalpos", p.arrivalPos, p.arrivalPosProcedure, error)) {
     235            3 :         WRITE_ERROR(error);
     236              :         ok = false;
     237              :     }
     238          163 :     if (oc.isSet("arrivalspeed") && !SUMOVehicleParameter::parseArrivalSpeed(oc.getString("arrivalspeed"), "option", "arrivalspeed", p.arrivalSpeed, p.arrivalSpeedProcedure, error)) {
     239            3 :         WRITE_ERROR(error);
     240              :         ok = false;
     241              :     }
     242          154 :     ok &= SystemFrame::checkOptions(oc);
     243          154 :     return ok;
     244          154 : }
     245              : 
     246              : 
     247              : 
     248              : 
     249              : /* -------------------------------------------------------------------------
     250              :  * main
     251              :  * ----------------------------------------------------------------------- */
     252              : int
     253          160 : main(int argc, char** argv) {
     254          160 :     OptionsCont& oc = OptionsCont::getOptions();
     255          160 :     oc.setApplicationDescription(TL("Importer of O/D-matrices for the microscopic, multi-modal traffic simulation SUMO."));
     256          320 :     oc.setApplicationName("od2trips", "Eclipse SUMO od2trips " VERSION_STRING);
     257              :     int ret = 0;
     258              :     try {
     259              :         // initialise subsystems
     260          160 :         XMLSubSys::init();
     261          160 :         fillOptions();
     262          160 :         OptionsIO::setArgs(argc, argv);
     263          160 :         OptionsIO::getOptions();
     264          160 :         if (oc.processMetaOptions(argc < 2)) {
     265            6 :             SystemFrame::close();
     266            6 :             return 0;
     267              :         }
     268          308 :         XMLSubSys::setValidation(oc.getString("xml-validation"), "never", "never");
     269          154 :         MsgHandler::initOutputOptions();
     270          154 :         if (!checkOptions()) {
     271           10 :             throw ProcessError();
     272              :         }
     273          144 :         RandHelper::initRandGlobal();
     274              :         // load the districts
     275              :         // check whether the user gave a net filename
     276          288 :         if (!oc.isSet("taz-files")) {
     277            0 :             throw ProcessError(TL("You must supply a TAZ, network or districts file ('-n')."));
     278              :         }
     279              :         // get the file name and set it
     280          144 :         ODDistrictCont districts;
     281          287 :         districts.loadDistricts(oc.getStringVector("taz-files"));
     282          143 :         if (districts.size() == 0) {
     283            0 :             throw ProcessError(TL("No districts loaded."));
     284              :         }
     285              :         // load the matrix
     286          143 :         ODMatrix matrix(districts, oc.getFloat("scale"));
     287          143 :         matrix.loadMatrix(oc);
     288          123 :         if (matrix.getNumLoaded() == 0) {
     289            0 :             throw ProcessError(TL("No vehicles loaded."));
     290              :         }
     291          153 :         if (MsgHandler::getErrorInstance()->wasInformed() && !oc.getBool("ignore-errors")) {
     292           28 :             throw ProcessError(TL("Loading failed."));
     293              :         }
     294          218 :         WRITE_MESSAGE(toString(matrix.getNumLoaded()) + " vehicles loaded.");
     295              :         // apply a curve if wished
     296          218 :         if (oc.isSet("timeline")) {
     297           22 :             matrix.applyCurve(matrix.parseTimeLine(oc.getStringVector("timeline"), oc.getBool("timeline.day-in-hours")));
     298              :         }
     299          109 :         const std::string modes = toString(oc.getStringVector("persontrips.modes"));
     300              :         // write
     301              :         bool haveOutput = false;
     302          111 :         const SUMOTime end = oc.isDefault("end") ? SUMOTime_MAX : string2time(oc.getString("end"));
     303          219 :         if (OutputDevice::createDeviceByOption("output-file", "routes", "routes_file.xsd")) {
     304          172 :             matrix.write(string2time(oc.getString("begin")), end,
     305          172 :                          OutputDevice::getDeviceByOption("output-file"),
     306          172 :                          oc.getBool("spread.uniform"), oc.getBool("different-source-sink"),
     307          172 :                          oc.getBool("ignore-vehicle-type"),
     308          172 :                          oc.getString("prefix"), !oc.getBool("no-step-log"),
     309          172 :                          oc.getBool("pedestrians"),
     310          172 :                          oc.getBool("persontrips"), modes);
     311              :             haveOutput = true;
     312              :         }
     313          216 :         if (OutputDevice::createDeviceByOption("flow-output", "routes", "routes_file.xsd")) {
     314           66 :             matrix.writeFlows(string2time(oc.getString("begin")), end,
     315           66 :                               OutputDevice::getDeviceByOption("flow-output"),
     316           99 :                               oc.getBool("ignore-vehicle-type"), oc.getString("prefix"),
     317           66 :                               oc.getBool("flow-output.probability"),
     318           66 :                               oc.getBool("flow-output.poisson"),
     319           66 :                               oc.getBool("pedestrians"),
     320           66 :                               oc.getBool("persontrips"), modes);
     321              :             haveOutput = true;
     322              :         }
     323           75 :         if (!haveOutput) {
     324            0 :             throw ProcessError(TL("No output file given."));
     325              :         }
     326          216 :         WRITE_MESSAGE(toString(matrix.getNumDiscarded()) + " vehicles discarded.");
     327          325 :         WRITE_MESSAGE(toString(matrix.getNumWritten()) + " vehicles written.");
     328          225 :     } catch (const ProcessError& e) {
     329          118 :         if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
     330           72 :             WRITE_ERROR(e.what());
     331              :         }
     332           46 :         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
     333              :         ret = 1;
     334              : #ifndef _DEBUG
     335           46 :     } catch (const std::exception& e) {
     336            0 :         if (std::string(e.what()) != std::string("")) {
     337            0 :             WRITE_ERROR(e.what());
     338              :         }
     339            0 :         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
     340              :         ret = 1;
     341            0 :     } catch (...) {
     342            0 :         MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
     343              :         ret = 1;
     344              : #endif
     345            0 :     }
     346          154 :     SystemFrame::close();
     347              :     if (ret == 0) {
     348              :         std::cout << "Success." << std::endl;
     349              :     }
     350              :     return ret;
     351              : }
     352              : 
     353              : 
     354              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1