Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 RODUAFrame.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // Sets and checks options for dua-routing
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <iostream>
25 : #include <fstream>
26 : #include <ctime>
27 : #include <utils/options/OptionsCont.h>
28 : #include <utils/options/Option.h>
29 : #include <utils/common/MsgHandler.h>
30 : #include <utils/common/UtilExceptions.h>
31 : #include <utils/common/ToString.h>
32 : #include "RODUAFrame.h"
33 : #include <router/ROFrame.h>
34 : #include <utils/common/RandHelper.h>
35 : #include <utils/common/SystemFrame.h>
36 : #include <utils/vehicle/SUMOVehicleParameter.h>
37 :
38 :
39 : // ===========================================================================
40 : // method definitions
41 : // ===========================================================================
42 : void
43 3737 : RODUAFrame::fillOptions() {
44 3737 : OptionsCont& oc = OptionsCont::getOptions();
45 7474 : oc.addCallExample("-c <CONFIGURATION>", TL("run routing with options from file"));
46 :
47 : // insert options sub-topics
48 3737 : SystemFrame::addConfigurationOptions(oc); // fill this subtopic, too
49 3737 : oc.addOptionSubTopic("Input");
50 3737 : oc.addOptionSubTopic("Output");
51 3737 : oc.addOptionSubTopic("Processing");
52 3737 : oc.addOptionSubTopic("Defaults");
53 3737 : oc.addOptionSubTopic("Time");
54 :
55 : // insert options
56 3737 : ROFrame::fillOptions(oc, true);
57 3737 : addImportOptions();
58 3737 : addDUAOptions();
59 : // add rand options
60 3737 : RandHelper::insertRandOptions(oc);
61 3737 : }
62 :
63 :
64 : void
65 3737 : RODUAFrame::addImportOptions() {
66 3737 : OptionsCont& oc = OptionsCont::getOptions();
67 3737 : oc.doRegister("alternatives-output", new Option_FileName());
68 7474 : oc.addSynonyme("alternatives-output", "alternatives");
69 7474 : oc.addDescription("alternatives-output", "Output", TL("Write generated route alternatives to FILE"));
70 :
71 3737 : oc.doRegister("intermodal-network-output", new Option_FileName());
72 7474 : oc.addDescription("intermodal-network-output", "Output", TL("Write edge splits and connectivity to FILE"));
73 :
74 3737 : oc.doRegister("intermodal-weight-output", new Option_FileName());
75 7474 : oc.addDescription("intermodal-weight-output", "Output", TL("Write intermodal edges with lengths and travel times to FILE"));
76 :
77 3737 : oc.doRegister("write-trips", new Option_Bool(false));
78 7474 : oc.addDescription("write-trips", "Output", TL("Write trips instead of vehicles (for validating trip input)"));
79 :
80 3737 : oc.doRegister("write-trips.geo", new Option_Bool(false));
81 7474 : oc.addDescription("write-trips.geo", "Output", TL("Write trips with geo-coordinates"));
82 :
83 3737 : oc.doRegister("write-trips.junctions", new Option_Bool(false));
84 7474 : oc.addDescription("write-trips.junctions", "Output", TL("Write trips with fromJunction and toJunction"));
85 :
86 3737 : oc.doRegister("write-costs", new Option_Bool(false));
87 7474 : oc.addDescription("write-costs", "Output", TL("Include the cost attribute in route output"));
88 :
89 : // register further processing options
90 : // ! The subtopic "Processing" must be initialised earlier !
91 3737 : oc.doRegister("weights.random-factor", new Option_Float(1.));
92 7474 : oc.addDescription("weights.random-factor", "Processing", TL("Edge weights for routing are dynamically disturbed by a random factor drawn uniformly from [1,FLOAT)"));
93 :
94 7474 : oc.doRegister("weight-period", new Option_String("3600", "TIME"));
95 7474 : oc.addDescription("weight-period", "Processing", TL("Aggregation period for the given weight files; triggers rebuilding of Contraction Hierarchy"));
96 :
97 3737 : oc.doRegister("weights.priority-factor", new Option_Float(0));
98 7474 : oc.addDescription("weights.priority-factor", "Processing", TL("Consider edge priorities in addition to travel times, weighted by factor"));
99 :
100 3737 : oc.doRegister("astar.all-distances", new Option_FileName());
101 7474 : oc.addDescription("astar.all-distances", "Processing", TL("Initialize lookup table for astar from the given file (generated by marouter --all-pairs-output)"));
102 :
103 3737 : oc.doRegister("astar.landmark-distances", new Option_FileName());
104 7474 : oc.addDescription("astar.landmark-distances", "Processing", TL("Initialize lookup table for astar ALT-variant from the given file"));
105 :
106 3737 : oc.doRegister("astar.save-landmark-distances", new Option_FileName());
107 7474 : oc.addDescription("astar.save-landmark-distances", "Processing", TL("Save lookup table for astar ALT-variant to the given file"));
108 :
109 3737 : oc.doRegister("scale", new Option_Float(1.));
110 7474 : oc.addDescription("scale", "Processing", TL("Scale demand by the given factor (by discarding or duplicating vehicles)"));
111 :
112 7474 : oc.doRegister("scale-suffix", new Option_String("."));
113 7474 : oc.addDescription("scale-suffix", "Processing", TL("Suffix to be added when creating ids for cloned vehicles"));
114 :
115 7474 : oc.doRegister("taxi.vclasses", new Option_StringVector({"taxi"}));
116 7474 : oc.addSynonyme("taxi.vclasses", "device.taxi.vclasses");
117 7474 : oc.addDescription("taxi.vclasses", "Processing", TL("Network permissions that can be accessed by taxis"));
118 3737 : }
119 :
120 :
121 : void
122 3737 : RODUAFrame::addDUAOptions() {
123 3737 : OptionsCont& oc = OptionsCont::getOptions();
124 : // register Gawron's DUE-settings
125 3737 : oc.doRegister("gawron.beta", new Option_Float(double(0.9)));
126 7474 : oc.addSynonyme("gawron.beta", "gBeta", true);
127 7474 : oc.addDescription("gawron.beta", "Processing", TL("Use FLOAT as Gawron's beta"));
128 :
129 3737 : oc.doRegister("gawron.a", new Option_Float(double(0.5)));
130 7474 : oc.addSynonyme("gawron.a", "gA", true);
131 7474 : oc.addDescription("gawron.a", "Processing", TL("Use FLOAT as Gawron's a"));
132 :
133 3737 : oc.doRegister("exit-times", new Option_Bool(false));
134 7474 : oc.addDescription("exit-times", "Output", TL("Write exit times (weights) for each edge"));
135 :
136 3737 : oc.doRegister("route-length", new Option_Bool(false));
137 7474 : oc.addDescription("route-length", "Output", TL("Include total route length in the output"));
138 :
139 3737 : oc.doRegister("keep-all-routes", new Option_Bool(false));
140 7474 : oc.addDescription("keep-all-routes", "Processing", TL("Save routes with near zero probability"));
141 :
142 3737 : oc.doRegister("skip-new-routes", new Option_Bool(false));
143 7474 : oc.addDescription("skip-new-routes", "Processing", TL("Only reuse routes from input, do not calculate new ones"));
144 :
145 3737 : oc.doRegister("keep-route-probability", new Option_Float(0));
146 7474 : oc.addDescription("keep-route-probability", "Processing", TL("The probability of keeping the old route"));
147 :
148 3737 : oc.doRegister("ptline-routing", new Option_Bool(false));
149 7474 : oc.addDescription("ptline-routing", "Processing", TL("Route all public transport input"));
150 :
151 3737 : oc.doRegister("keep-flows", new Option_Bool(false));
152 7474 : oc.addDescription("keep-flows", "Processing", TL("Write flows instead of expanding them into vehicles"));
153 :
154 7474 : oc.doRegister("route-choice-method", new Option_String("gawron"));
155 7474 : oc.addDescription("route-choice-method", "Processing", TL("Choose a route choice method: gawron, logit, or lohse"));
156 :
157 3737 : oc.doRegister("logit", new Option_Bool(false)); // deprecated
158 7474 : oc.addDescription("logit", "Processing", TL("Use c-logit model (deprecated in favor of --route-choice-method logit)"));
159 :
160 3737 : oc.doRegister("logit.beta", new Option_Float(double(-1)));
161 7474 : oc.addSynonyme("logit.beta", "lBeta", true);
162 7474 : oc.addDescription("logit.beta", "Processing", TL("Use FLOAT as logit's beta"));
163 :
164 3737 : oc.doRegister("logit.gamma", new Option_Float(double(1)));
165 7474 : oc.addSynonyme("logit.gamma", "lGamma", true);
166 7474 : oc.addDescription("logit.gamma", "Processing", TL("Use FLOAT as logit's gamma"));
167 :
168 3737 : oc.doRegister("logit.theta", new Option_Float(double(-1)));
169 7474 : oc.addSynonyme("logit.theta", "lTheta", true);
170 7474 : oc.addDescription("logit.theta", "Processing", TL("Use FLOAT as logit's theta (negative values mean auto-estimation)"));
171 :
172 3737 : oc.doRegister("persontrip.walkfactor", new Option_Float(double(0.75)));
173 7474 : oc.addDescription("persontrip.walkfactor", "Processing", TL("Use FLOAT as a factor on pedestrian maximum speed during intermodal routing"));
174 :
175 3737 : oc.doRegister("persontrip.walk-opposite-factor", new Option_Float(1.0));
176 7474 : oc.addDescription("persontrip.walk-opposite-factor", "Processing", TL("Use FLOAT as a factor on walking speed against vehicle traffic direction"));
177 :
178 14948 : oc.doRegister("persontrip.transfer.car-walk", new Option_StringVector(StringVector({ "parkingAreas" })));
179 7474 : oc.addDescription("persontrip.transfer.car-walk", "Processing",
180 : "Where are mode changes from car to walking allowed (possible values: 'parkingAreas', 'ptStops', 'allJunctions' and combinations)");
181 :
182 3737 : oc.doRegister("persontrip.transfer.taxi-walk", new Option_StringVector());
183 7474 : oc.addDescription("persontrip.transfer.taxi-walk", "Processing", TL("Where taxis can drop off customers ('allJunctions, 'ptStops')"));
184 :
185 3737 : oc.doRegister("persontrip.transfer.walk-taxi", new Option_StringVector());
186 7474 : oc.addDescription("persontrip.transfer.walk-taxi", "Processing", TL("Where taxis can pick up customers ('allJunctions, 'ptStops')"));
187 :
188 7474 : oc.doRegister("persontrip.taxi.waiting-time", new Option_String("300", "TIME"));
189 7474 : oc.addDescription("persontrip.taxi.waiting-time", "Processing", TL("Estimated time for taxi pickup"));
190 :
191 3737 : oc.doRegister("persontrip.ride-public-line", new Option_Bool(false));
192 7474 : oc.addDescription("persontrip.ride-public-line", "Processing", TL("Only use the intended public transport line rather than any alternative line that stops at the destination"));
193 :
194 3737 : oc.doRegister("railway.max-train-length", new Option_Float(1000.0));
195 7474 : oc.addDescription("railway.max-train-length", "Processing", TL("Use FLOAT as a maximum train length when initializing the railway router"));
196 :
197 7474 : oc.doRegister("max-traveltime", new Option_String("-1", "TIME"));
198 7474 : oc.addDescription("max-traveltime", "Processing", TL("Declare routing failure if traveltime exceeds the given positive TIME"));
199 11211 : }
200 :
201 :
202 : bool
203 3478 : RODUAFrame::checkOptions() {
204 3478 : OptionsCont& oc = OptionsCont::getOptions();
205 3478 : bool ok = ROFrame::checkOptions(oc);
206 :
207 3478 : SUMOVehicleParameter p;
208 : std::string error;
209 3534 : if (oc.isSet("departlane") && !SUMOVehicleParameter::parseDepartLane(oc.getString("departlane"), "option", "departlane", p.departLane, p.departLaneProcedure, error)) {
210 12 : WRITE_ERROR(error);
211 : ok = false;
212 : }
213 3534 : if (oc.isSet("departpos") && !SUMOVehicleParameter::parseDepartPos(oc.getString("departpos"), "option", "departpos", p.departPos, p.departPosProcedure, error)) {
214 12 : WRITE_ERROR(error);
215 : ok = false;
216 : }
217 3534 : if (oc.isSet("departspeed") && !SUMOVehicleParameter::parseDepartSpeed(oc.getString("departspeed"), "option", "departspeed", p.departSpeed, p.departSpeedProcedure, error)) {
218 12 : WRITE_ERROR(error);
219 : ok = false;
220 : }
221 3534 : if (oc.isSet("arrivallane") && !SUMOVehicleParameter::parseArrivalLane(oc.getString("arrivallane"), "option", "arrivallane", p.arrivalLane, p.arrivalLaneProcedure, error)) {
222 12 : WRITE_ERROR(error);
223 : ok = false;
224 : }
225 3534 : if (oc.isSet("arrivalpos") && !SUMOVehicleParameter::parseArrivalPos(oc.getString("arrivalpos"), "option", "arrivalpos", p.arrivalPos, p.arrivalPosProcedure, error)) {
226 12 : WRITE_ERROR(error);
227 : ok = false;
228 : }
229 3534 : if (oc.isSet("arrivalspeed") && !SUMOVehicleParameter::parseArrivalSpeed(oc.getString("arrivalspeed"), "option", "arrivalspeed", p.arrivalSpeed, p.arrivalSpeedProcedure, error)) {
230 12 : WRITE_ERROR(error);
231 : ok = false;
232 : }
233 :
234 9154 : if (oc.getString("routing-algorithm") != "dijkstra" && oc.getString("weight-attribute") != "traveltime") {
235 9 : WRITE_ERRORF(TL("Routing algorithm '%' does not support weight-attribute '%'."), oc.getString("routing-algorithm"), oc.getString("weight-attribute"));
236 3 : return false;
237 : }
238 3663 : if (oc.getBool("bulk-routing") && (oc.getString("routing-algorithm") == "CH" || oc.getString("routing-algorithm") == "CHWrapper")) {
239 24 : WRITE_ERRORF(TL("Routing algorithm '%' does not support bulk routing."), oc.getString("routing-algorithm"));
240 12 : return false;
241 : }
242 7680 : if (oc.isDefault("routing-algorithm") && (oc.isSet("astar.all-distances") || oc.isSet("astar.landmark-distances") || oc.isSet("astar.save-landmark-distances"))) {
243 20 : oc.setDefault("routing-algorithm", "astar");
244 : }
245 3485 : if (!oc.isDefault("weights.random-factor") && (oc.isSet("astar.all-distances") || oc.isSet("astar.landmark-distances") || oc.isSet("astar.save-landmark-distances"))) {
246 4 : WRITE_WARNING(TL("The option --weights.random-factor should not be used together with astar and precomputed distances."));
247 : }
248 :
249 3625 : if (oc.getString("route-choice-method") != "gawron" && oc.getString("route-choice-method") != "logit") {
250 0 : WRITE_ERRORF(TL("Invalid route choice method '%'."), oc.getString("route-choice-method"));
251 0 : return false;
252 : }
253 6926 : if (oc.getBool("logit")) {
254 0 : WRITE_WARNING(TL("The --logit option is deprecated, please use --route-choice-method logit."));
255 0 : oc.set("route-choice-method", "logit");
256 : }
257 :
258 7185 : if (oc.isSet("output-file") && !oc.isSet("alternatives-output")) {
259 6376 : const std::string& filename = oc.getString("output-file");
260 3188 : const int len = (int)filename.length();
261 6375 : if (len > 4 && filename.substr(len - 4) == ".xml") {
262 12080 : oc.setDefault("alternatives-output", filename.substr(0, len - 4) + ".alt.xml");
263 335 : } else if (len > 7 && filename.substr(len - 7) == ".xml.gz") {
264 668 : oc.setDefault("alternatives-output", filename.substr(0, len - 7) + ".alt.xml.gz");
265 1 : } else if (len > 3 && filename.substr(len - 3) == ".gz") {
266 0 : oc.setDefault("alternatives-output", filename.substr(0, len - 3) + ".alt.gz");
267 : } else {
268 2 : WRITE_WARNING(TL("Cannot derive file name for alternatives output, skipping it."));
269 : }
270 : }
271 6926 : if (oc.getBool("write-trips.junctions")) {
272 40 : if (oc.isDefault("write-trips")) {
273 8 : oc.setDefault("write-trips", "true");
274 32 : } else if (!oc.getBool("write-trips")) {
275 0 : WRITE_WARNING(TL("Option --write-trips.junctions takes no affect when --write-trips is disabled."));
276 : }
277 : }
278 3463 : gTaxiClasses = 0;
279 10389 : for (const std::string& vClassName : oc.getStringVector("device.taxi.vclasses")) {
280 3463 : gTaxiClasses |= parseVehicleClasses(vClassName);
281 : }
282 : return ok;
283 3478 : }
284 :
285 :
286 : /****************************************************************************/
|