Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-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 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 : #ifdef HAVE_FOX
42 : #include <utils/foxtools/MsgHandlerSynchronized.h>
43 : #endif
44 : #include <utils/iodevices/OutputDevice.h>
45 : #include <utils/options/Option.h>
46 : #include <utils/options/OptionsCont.h>
47 : #include <utils/options/OptionsIO.h>
48 : #include <utils/router/DijkstraRouter.h>
49 : #include <utils/router/AStarRouter.h>
50 : #include <utils/router/CHRouter.h>
51 : #include <utils/router/CHRouterWrapper.h>
52 : #include <utils/xml/XMLSubSys.h>
53 : #include <router/ROFrame.h>
54 : #include <router/ROLoader.h>
55 : #include <router/RONet.h>
56 : #include <router/ROEdge.h>
57 : #include "RODUAEdgeBuilder.h"
58 : #include "RODUAFrame.h"
59 :
60 :
61 : // ===========================================================================
62 : // functions
63 : // ===========================================================================
64 : /* -------------------------------------------------------------------------
65 : * data processing methods
66 : * ----------------------------------------------------------------------- */
67 : /**
68 : * loads the net
69 : * The net is in this meaning made up by the net itself and the dynamic
70 : * weights which may be supplied in a separate file
71 : */
72 : void
73 3609 : initNet(RONet& net, ROLoader& loader, OptionsCont& oc) {
74 : // load the net
75 3609 : RODUAEdgeBuilder builder;
76 3609 : ROEdge::setGlobalOptions(oc.getBool("weights.interpolate"));
77 3609 : loader.loadNet(net, builder);
78 : // load the weights when wished/available
79 6258 : if (oc.isSet("weight-files")) {
80 2172 : loader.loadWeights(net, "weight-files", oc.getString("weight-attribute"), false, oc.getBool("weights.expand"));
81 : }
82 6258 : if (oc.isSet("lane-weight-files")) {
83 6 : loader.loadWeights(net, "lane-weight-files", oc.getString("weight-attribute"), true, oc.getBool("weights.expand"));
84 : }
85 3609 : }
86 :
87 :
88 : /**
89 : * Computes the routes saving them
90 : */
91 : void
92 3129 : computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
93 : // initialise the loader
94 3129 : loader.openRoutes(net);
95 : // build the router
96 2691 : auto ttFunction = gWeightsRandomFactor > 1 ? &ROEdge::getTravelTimeStaticRandomized : &ROEdge::getTravelTimeStatic;
97 : SUMOAbstractRouter<ROEdge, ROVehicle>* router;
98 2691 : const std::string measure = oc.getString("weight-attribute");
99 2735 : const std::string routingAlgorithm = oc.getString("routing-algorithm");
100 2691 : const double priorityFactor = oc.getFloat("weights.priority-factor");
101 5382 : const SUMOTime begin = string2time(oc.getString("begin"));
102 2887 : const SUMOTime end = oc.isDefault("end") ? SUMOTime_MAX : string2time(oc.getString("end"));
103 : DijkstraRouter<ROEdge, ROVehicle>::Operation op = &ROEdge::getTravelTimeStatic;
104 :
105 5394 : if (oc.isSet("restriction-params") &&
106 9 : (routingAlgorithm == "CH" || routingAlgorithm == "CHWrapper")) {
107 24 : throw ProcessError(TLF("Routing algorithm '%' does not support restriction-params", routingAlgorithm));
108 : }
109 :
110 2685 : if (measure == "traveltime" && priorityFactor == 0) {
111 2670 : if (routingAlgorithm == "dijkstra") {
112 2696 : router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, nullptr, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
113 1322 : } else if (routingAlgorithm == "astar") {
114 : typedef AStarRouter<ROEdge, ROVehicle> AStar;
115 459 : std::shared_ptr<const AStar::LookupTable> lookup;
116 918 : if (oc.isSet("astar.all-distances")) {
117 0 : lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)ROEdge::getAllEdges().size());
118 918 : } else if (oc.isSet("astar.landmark-distances")) {
119 : /* CHRouterWrapper<ROEdge, ROVehicle> chrouter(
120 : ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic,
121 : begin, end, SUMOTime_MAX, 1); */
122 10 : DijkstraRouter<ROEdge, ROVehicle> forward(ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic);
123 : std::vector<ReversedEdge<ROEdge, ROVehicle>*> reversed;
124 20498 : for (ROEdge* edge : ROEdge::getAllEdges()) {
125 20490 : reversed.push_back(edge->getReversedRoutingEdge());
126 : }
127 20498 : for (ReversedEdge<ROEdge, ROVehicle>* redge : reversed) {
128 20488 : redge->init();
129 : }
130 10 : DijkstraRouter<ReversedEdge<ROEdge, ROVehicle>, ROVehicle> backward(reversed, true, &ReversedEdge<ROEdge, ROVehicle>::getTravelTimeStatic);
131 12 : ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
132 30 : lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), ROEdge::getAllEdges(), &forward, &backward, &defaultVehicle,
133 36 : oc.isSet("astar.save-landmark-distances") ? oc.getString("astar.save-landmark-distances") : "", oc.getInt("routing-threads"));
134 10 : }
135 924 : router = new AStar(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, lookup, net.hasPermissions(), oc.isSet("restriction-params"));
136 863 : } else if (routingAlgorithm == "CH" && !net.hasPermissions()) {
137 65 : const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
138 83 : string2time(oc.getString("weight-period")) :
139 : SUMOTime_MAX);
140 : router = new CHRouter<ROEdge, ROVehicle>(
141 130 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, SVC_IGNORING, weightPeriod, net.hasPermissions(), oc.isSet("restriction-params"));
142 1163 : } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
143 : // use CHWrapper instead of CH if the net has permissions
144 798 : const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
145 820 : string2time(oc.getString("weight-period")) :
146 : SUMOTime_MAX);
147 : router = new CHRouterWrapper<ROEdge, ROVehicle>(
148 1596 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction,
149 1596 : begin, end, weightPeriod, net.hasPermissions(), oc.getInt("routing-threads"));
150 : } else {
151 0 : throw ProcessError(TLF("Unknown routing Algorithm '%'!", routingAlgorithm));
152 : }
153 : } else {
154 15 : if (measure == "traveltime") {
155 3 : if (ROEdge::initPriorityFactor(priorityFactor)) {
156 : op = &ROEdge::getTravelTimeStaticPriorityFactor;
157 : }
158 12 : } else if (measure == "CO") {
159 : op = &ROEdge::getEmissionEffort<PollutantsInterface::CO>;
160 8 : } else if (measure == "CO2") {
161 : op = &ROEdge::getEmissionEffort<PollutantsInterface::CO2>;
162 7 : } else if (measure == "PMx") {
163 : op = &ROEdge::getEmissionEffort<PollutantsInterface::PM_X>;
164 6 : } else if (measure == "HC") {
165 : op = &ROEdge::getEmissionEffort<PollutantsInterface::HC>;
166 4 : } else if (measure == "NOx") {
167 : op = &ROEdge::getEmissionEffort<PollutantsInterface::NO_X>;
168 3 : } else if (measure == "fuel") {
169 : op = &ROEdge::getEmissionEffort<PollutantsInterface::FUEL>;
170 2 : } else if (measure == "electricity") {
171 : op = &ROEdge::getEmissionEffort<PollutantsInterface::ELEC>;
172 2 : } else if (measure == "noise") {
173 : op = &ROEdge::getNoiseEffort;
174 : } else {
175 : op = &ROEdge::getStoredEffort;
176 : }
177 15 : if (measure != "traveltime" && !net.hasLoadedEffort()) {
178 9 : WRITE_WARNINGF(TL("No weight data was loaded for attribute '%'."), measure);
179 : }
180 : router = new DijkstraRouter<ROEdge, ROVehicle>(
181 30 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), op, ttFunction, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
182 : }
183 : int carWalk = 0;
184 8049 : for (const std::string& opt : oc.getStringVector("persontrip.transfer.car-walk")) {
185 2683 : if (opt == "parkingAreas") {
186 2639 : carWalk |= ROIntermodalRouter::Network::PARKING_AREAS;
187 44 : } else if (opt == "ptStops") {
188 36 : carWalk |= ROIntermodalRouter::Network::PT_STOPS;
189 8 : } else if (opt == "allJunctions") {
190 8 : carWalk |= ROIntermodalRouter::Network::ALL_JUNCTIONS;
191 : }
192 : }
193 5394 : for (const std::string& opt : oc.getStringVector("persontrip.transfer.taxi-walk")) {
194 28 : if (opt == "ptStops") {
195 12 : carWalk |= ROIntermodalRouter::Network::TAXI_DROPOFF_PT;
196 16 : } else if (opt == "allJunctions") {
197 16 : carWalk |= ROIntermodalRouter::Network::TAXI_DROPOFF_ANYWHERE;
198 : }
199 : }
200 5394 : for (const std::string& opt : oc.getStringVector("persontrip.transfer.walk-taxi")) {
201 28 : if (opt == "ptStops") {
202 12 : carWalk |= ROIntermodalRouter::Network::TAXI_PICKUP_PT;
203 16 : } else if (opt == "allJunctions") {
204 16 : carWalk |= ROIntermodalRouter::Network::TAXI_PICKUP_ANYWHERE;
205 : }
206 : }
207 5366 : double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
208 :
209 : RailwayRouter<ROEdge, ROVehicle>* railRouter = nullptr;
210 2683 : if (net.hasBidiEdges()) {
211 47 : railRouter = new RailwayRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), true, op, ttFunction, false, net.hasPermissions(),
212 138 : oc.isSet("restriction-params"),
213 94 : oc.getFloat("railway.max-train-length"));
214 : }
215 2683 : RORouterProvider provider(router, new PedestrianRouter<ROEdge, ROLane, RONode, ROVehicle>(),
216 2683 : new ROIntermodalRouter(RONet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm),
217 : railRouter);
218 : // process route definitions
219 : try {
220 2683 : net.openOutput(oc);
221 5358 : loader.processRoutes(begin, end, string2time(oc.getString("route-steps")), net, provider);
222 2647 : net.writeIntermodal(oc, provider.getIntermodalRouter());
223 : // end the processing
224 2647 : net.cleanup();
225 36 : } catch (ProcessError&) {
226 36 : net.cleanup();
227 36 : throw;
228 36 : }
229 5330 : }
230 :
231 :
232 : /* -------------------------------------------------------------------------
233 : * main
234 : * ----------------------------------------------------------------------- */
235 : int
236 4119 : main(int argc, char** argv) {
237 4119 : OptionsCont& oc = OptionsCont::getOptions();
238 4119 : oc.setApplicationDescription(TL("Shortest path router and DUE computer for the microscopic, multi-modal traffic simulation SUMO."));
239 8238 : oc.setApplicationName("duarouter", "Eclipse SUMO duarouter Version " VERSION_STRING);
240 : int ret = 0;
241 : RONet* net = nullptr;
242 : try {
243 4119 : XMLSubSys::init();
244 4119 : RODUAFrame::fillOptions();
245 4119 : OptionsIO::setArgs(argc, argv);
246 4119 : OptionsIO::getOptions();
247 4115 : if (oc.processMetaOptions(argc < 2)) {
248 465 : SystemFrame::close();
249 465 : return 0;
250 : }
251 3650 : SystemFrame::checkOptions(oc);
252 10950 : XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
253 : #ifdef HAVE_FOX
254 7300 : if (oc.getInt("routing-threads") > 1) {
255 : // make the output aware of threading
256 : MsgHandler::setFactory(&MsgHandlerSynchronized::create);
257 : }
258 : #endif
259 3650 : MsgHandler::initOutputOptions();
260 3650 : if (!RODUAFrame::checkOptions()) {
261 41 : throw ProcessError();
262 : }
263 3609 : RandHelper::initRandGlobal();
264 : // load data
265 3609 : ROLoader loader(oc, false, !oc.getBool("no-step-log"));
266 3609 : net = new RONet();
267 3609 : initNet(*net, loader, oc);
268 : // build routes
269 : try {
270 3129 : computeRoutes(*net, loader, oc);
271 482 : } catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
272 0 : WRITE_ERROR(toString(e.getLineNumber()));
273 : ret = 1;
274 0 : } catch (XERCES_CPP_NAMESPACE::SAXException& e) {
275 0 : WRITE_ERROR(StringUtils::transcode(e.getMessage()));
276 : ret = 1;
277 0 : }
278 2647 : if (MsgHandler::getErrorInstance()->wasInformed() || ret != 0) {
279 172 : throw ProcessError();
280 : }
281 4788 : } catch (const ProcessError& e) {
282 2505 : if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
283 844 : WRITE_ERROR(e.what());
284 : }
285 1179 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
286 : ret = 1;
287 : #ifndef _DEBUG
288 1179 : } catch (const std::exception& e) {
289 0 : if (std::string(e.what()) != std::string("")) {
290 0 : WRITE_ERROR(e.what());
291 : }
292 0 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
293 : ret = 1;
294 0 : } catch (...) {
295 0 : MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
296 : ret = 1;
297 : #endif
298 0 : }
299 3654 : delete net;
300 3654 : SystemFrame::close();
301 3654 : if (ret == 0) {
302 : std::cout << "Success." << std::endl;
303 : }
304 : return ret;
305 : }
306 :
307 :
308 : /****************************************************************************/
|