LCOV - code coverage report
Current view: top level - src - od2trips_main.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 159 170 93.5 %
Date: 2024-05-04 15:27:10 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.14