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 : #include <utils/vehicle/SUMORouteHandler.h>
42 : #ifdef HAVE_FOX
43 : #include <utils/foxtools/MsgHandlerSynchronized.h>
44 : #endif
45 : #include <utils/iodevices/OutputDevice.h>
46 : #include <utils/options/Option.h>
47 : #include <utils/options/OptionsCont.h>
48 : #include <utils/options/OptionsIO.h>
49 : #include <utils/router/DijkstraRouter.h>
50 : #include <utils/router/AFRouter.h>
51 : #include <utils/router/AStarRouter.h>
52 : #include <utils/router/CHRouter.h>
53 : #include <utils/router/CHRouterWrapper.h>
54 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
55 : #include <utils/xml/XMLSubSys.h>
56 : #include <router/ROFrame.h>
57 : #include <router/ROLoader.h>
58 : #include <router/RONet.h>
59 : #include <router/ROEdge.h>
60 : #include "RODUAEdgeBuilder.h"
61 : #include "RODUAFrame.h"
62 :
63 :
64 : // ===========================================================================
65 : // functions
66 : // ===========================================================================
67 : /* -------------------------------------------------------------------------
68 : * data processing methods
69 : * ----------------------------------------------------------------------- */
70 : /**
71 : * loads the net
72 : * The net is in this meaning made up by the net itself and the dynamic
73 : * weights which may be supplied in a separate file
74 : */
75 : void
76 9134 : initNet(RONet& net, ROLoader& loader, OptionsCont& oc) {
77 : // load the net
78 9134 : RODUAEdgeBuilder builder;
79 9134 : ROEdge::setGlobalOptions(oc.getBool("weights.interpolate"));
80 9134 : loader.loadNet(net, builder);
81 : // load the weights when wished/available
82 17776 : if (oc.isSet("weight-files")) {
83 1194 : loader.loadWeights(net, "weight-files", oc.getString("weight-attribute"), false, oc.getBool("weights.expand"));
84 : }
85 17776 : if (oc.isSet("lane-weight-files")) {
86 6 : loader.loadWeights(net, "lane-weight-files", oc.getString("weight-attribute"), true, oc.getBool("weights.expand"));
87 : }
88 9134 : }
89 :
90 :
91 : /**
92 : * Computes the routes saving them
93 : */
94 : void
95 8888 : computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
96 : // initialise the loader
97 8888 : loader.openRoutes(net);
98 : // build the router
99 6039 : auto ttFunction = gWeightsRandomFactor > 1 ? &ROEdge::getTravelTimeStaticRandomized : &ROEdge::getTravelTimeStatic;
100 : SUMOAbstractRouter<ROEdge, ROVehicle>* router;
101 6039 : const std::string measure = oc.getString("weight-attribute");
102 6083 : const std::string routingAlgorithm = oc.getString("routing-algorithm");
103 6039 : const double priorityFactor = oc.getFloat("weights.priority-factor");
104 6039 : const SUMOTime begin = string2time(oc.getString("begin"));
105 6171 : const SUMOTime end = oc.isDefault("end") ? SUMOTime_MAX : string2time(oc.getString("end"));
106 : DijkstraRouter<ROEdge, ROVehicle>::Operation op = &ROEdge::getTravelTimeStatic;
107 :
108 12078 : if (oc.isSet("restriction-params") &&
109 12 : (routingAlgorithm == "CH" || routingAlgorithm == "CHWrapper")) {
110 18 : throw ProcessError(TLF("Routing algorithm '%' does not support restriction-params", routingAlgorithm));
111 : }
112 :
113 6033 : if (measure == "traveltime" && priorityFactor == 0) {
114 6019 : if (routingAlgorithm == "dijkstra") {
115 9332 : router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, nullptr, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
116 1353 : } else if (routingAlgorithm == "astar") {
117 : typedef AStarRouter<ROEdge, ROVehicle, ROMapMatcher> AStar;
118 465 : std::shared_ptr<const AStar::LookupTable> lookup;
119 930 : if (oc.isSet("astar.all-distances")) {
120 0 : lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)ROEdge::getAllEdges().size());
121 932 : } else if (oc.isSet("astar.landmark-distances")) {
122 : /* CHRouterWrapper<ROEdge, ROVehicle> chrouter(
123 : ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic,
124 : begin, end, SUMOTime_MAX, 1); */
125 14 : DijkstraRouter<ROEdge, ROVehicle> forward(ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic);
126 : std::vector<ReversedEdge<ROEdge, ROVehicle>*> reversed;
127 21262 : for (ROEdge* edge : ROEdge::getAllEdges()) {
128 21248 : reversed.push_back(edge->getReversedRoutingEdge());
129 : }
130 21262 : for (ReversedEdge<ROEdge, ROVehicle>* redge : reversed) {
131 21248 : redge->init();
132 : }
133 14 : DijkstraRouter<ReversedEdge<ROEdge, ROVehicle>, ROVehicle> backward(reversed, true, &ReversedEdge<ROEdge, ROVehicle>::getTravelTimeStatic);
134 16 : ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
135 14 : ROMapMatcher* mapMatcher = dynamic_cast<ROMapMatcher*>(loader.getRouteHandler());
136 28 : lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), ROEdge::getAllEdges(), &forward, &backward, &defaultVehicle,
137 40 : oc.isSet("astar.save-landmark-distances") ? oc.getString("astar.save-landmark-distances") : "", oc.getInt("routing-threads"), mapMatcher);
138 28 : }
139 938 : router = new AStar(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, lookup, net.hasPermissions(), oc.isSet("restriction-params"));
140 888 : } else if (routingAlgorithm == "CH" && !net.hasPermissions()) {
141 65 : const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
142 83 : string2time(oc.getString("weight-period")) :
143 : SUMOTime_MAX);
144 : router = new CHRouter<ROEdge, ROVehicle>(
145 130 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, SVC_IGNORING, weightPeriod, net.hasPermissions(), oc.isSet("restriction-params"));
146 823 : } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
147 : // use CHWrapper instead of CH if the net has permissions
148 823 : const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
149 845 : string2time(oc.getString("weight-period")) :
150 : SUMOTime_MAX);
151 : router = new CHRouterWrapper<ROEdge, ROVehicle>(
152 1646 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction,
153 2469 : begin, end, weightPeriod, net.hasPermissions(), oc.getInt("routing-threads"));
154 0 : } else if (routingAlgorithm == "arcflag") {
155 : /// @brief The number of levels in the k-d tree partition
156 : constexpr auto NUMBER_OF_LEVELS = 5; //or 4 or 8
157 0 : ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
158 0 : KDTreePartition<ROEdge, RONode, ROVehicle>* partition = new KDTreePartition<ROEdge, RONode, ROVehicle>(NUMBER_OF_LEVELS, ROEdge::getAllEdges(), net.hasPermissions(), oc.isSet("restriction-params"));
159 0 : partition->init(&defaultVehicle);
160 0 : auto ttFunction = gWeightsRandomFactor > 1 ? &ROEdge::getTravelTimeStaticRandomized : &ROEdge::getTravelTimeStatic;
161 0 : auto reversedTtFunction = gWeightsRandomFactor > 1 ? &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStaticRandomized : &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStatic;
162 0 : router = new AFRouter<ROEdge, RONode, ROVehicle, ROMapMatcher>(ROEdge::getAllEdges(),
163 0 : partition, oc.getBool("ignore-errors"), ttFunction, reversedTtFunction, (oc.isSet("weight-files") ? string2time(oc.getString("weight-period")) : SUMOTime_MAX),
164 0 : nullptr, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
165 0 : } else {
166 0 : throw ProcessError(TLF("Unknown routing Algorithm '%'!", routingAlgorithm));
167 : }
168 : } else {
169 14 : if (measure == "traveltime") {
170 3 : if (ROEdge::initPriorityFactor(priorityFactor)) {
171 : op = &ROEdge::getTravelTimeStaticPriorityFactor;
172 : }
173 11 : } else if (measure == "CO") {
174 : op = &ROEdge::getEmissionEffort<PollutantsInterface::CO>;
175 8 : } else if (measure == "CO2") {
176 : op = &ROEdge::getEmissionEffort<PollutantsInterface::CO2>;
177 7 : } else if (measure == "PMx") {
178 : op = &ROEdge::getEmissionEffort<PollutantsInterface::PM_X>;
179 6 : } else if (measure == "HC") {
180 : op = &ROEdge::getEmissionEffort<PollutantsInterface::HC>;
181 4 : } else if (measure == "NOx") {
182 : op = &ROEdge::getEmissionEffort<PollutantsInterface::NO_X>;
183 3 : } else if (measure == "fuel") {
184 : op = &ROEdge::getEmissionEffort<PollutantsInterface::FUEL>;
185 2 : } else if (measure == "electricity") {
186 : op = &ROEdge::getEmissionEffort<PollutantsInterface::ELEC>;
187 2 : } else if (measure == "noise") {
188 : op = &ROEdge::getNoiseEffort;
189 : } else {
190 : op = &ROEdge::getStoredEffort;
191 : }
192 14 : if (measure != "traveltime" && !net.hasLoadedEffort()) {
193 6 : WRITE_WARNINGF(TL("No weight data was loaded for attribute '%'."), measure);
194 : }
195 : router = new DijkstraRouter<ROEdge, ROVehicle>(
196 28 : ROEdge::getAllEdges(), oc.getBool("ignore-errors"), op, ttFunction, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
197 : }
198 6031 : const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc);
199 12106 : double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
200 :
201 : RailwayRouter<ROEdge, ROVehicle>* railRouter = nullptr;
202 6031 : if (net.hasBidiEdges()) {
203 80 : railRouter = new RailwayRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), true, op, ttFunction, false, net.hasPermissions(),
204 80 : oc.isSet("restriction-params"),
205 120 : oc.getFloat("railway.max-train-length"));
206 : }
207 6031 : RORouterProvider provider(router, new PedestrianRouter<ROEdge, ROLane, RONode, ROVehicle>(),
208 6031 : new ROIntermodalRouter(RONet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm),
209 : railRouter);
210 : // process route definitions
211 : try {
212 6031 : net.openOutput(oc);
213 12022 : loader.processRoutes(begin, end, string2time(oc.getString("route-steps")), net, provider);
214 5995 : net.writeIntermodal(oc, provider.getIntermodalRouter());
215 : // end the processing
216 5995 : net.cleanup();
217 36 : } catch (ProcessError&) {
218 36 : net.cleanup();
219 36 : throw;
220 36 : }
221 12026 : }
222 :
223 :
224 : /* -------------------------------------------------------------------------
225 : * main
226 : * ----------------------------------------------------------------------- */
227 : int
228 9427 : main(int argc, char** argv) {
229 9427 : OptionsCont& oc = OptionsCont::getOptions();
230 9427 : oc.setApplicationDescription(TL("Shortest path router and DUE computer for the microscopic, multi-modal traffic simulation SUMO."));
231 18854 : oc.setApplicationName("duarouter", "Eclipse SUMO duarouter Version " VERSION_STRING);
232 : int ret = 0;
233 : RONet* net = nullptr;
234 : try {
235 9427 : XMLSubSys::init();
236 9427 : RODUAFrame::fillOptions();
237 9427 : OptionsIO::setArgs(argc, argv);
238 9427 : OptionsIO::getOptions();
239 9423 : if (oc.processMetaOptions(argc < 2)) {
240 248 : SystemFrame::close();
241 248 : return 0;
242 : }
243 9175 : SystemFrame::checkOptions(oc);
244 27525 : XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
245 : #ifdef HAVE_FOX
246 18350 : if (oc.getInt("routing-threads") > 1) {
247 : // make the output aware of threading
248 : MsgHandler::setFactory(&MsgHandlerSynchronized::create);
249 : }
250 : #endif
251 9175 : MsgHandler::initOutputOptions();
252 9175 : if (!RODUAFrame::checkOptions()) {
253 41 : throw ProcessError();
254 : }
255 9134 : RandHelper::initRandGlobal();
256 : // load data
257 12489 : ROLoader loader(oc, false, !oc.getBool("no-step-log"));
258 9134 : net = new RONet();
259 9134 : initNet(*net, loader, oc);
260 : // build routes
261 : try {
262 8888 : computeRoutes(*net, loader, oc);
263 2893 : } catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
264 0 : WRITE_ERROR(toString(e.getLineNumber()));
265 : ret = 1;
266 0 : } catch (XERCES_CPP_NAMESPACE::SAXException& e) {
267 0 : WRITE_ERROR(StringUtils::transcode(e.getMessage()));
268 : ret = 1;
269 0 : }
270 5995 : if (MsgHandler::getErrorInstance()->wasInformed() || ret != 0) {
271 171 : throw ProcessError();
272 : }
273 12489 : } catch (const ProcessError& e) {
274 7329 : if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
275 3914 : WRITE_ERROR(e.what());
276 : }
277 3355 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
278 : ret = 1;
279 : #ifndef _DEBUG
280 3355 : } catch (const std::exception& e) {
281 0 : if (std::string(e.what()) != std::string("")) {
282 0 : WRITE_ERROR(e.what());
283 : }
284 0 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
285 : ret = 1;
286 0 : } catch (...) {
287 0 : MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
288 : ret = 1;
289 : #endif
290 0 : }
291 9179 : delete net;
292 9179 : SystemFrame::close();
293 9179 : if (ret == 0) {
294 : std::cout << "Success." << std::endl;
295 : }
296 : return ret;
297 : }
298 :
299 :
300 : /****************************************************************************/
|