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 : /****************************************************************************/
|