Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/duarouter/duarouter_main.cpp
193735 views
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 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
initNet(RONet& net, ROLoader& loader, OptionsCont& oc) {
77
// load the net
78
RODUAEdgeBuilder builder;
79
ROEdge::setGlobalOptions(oc.getBool("weights.interpolate"));
80
loader.loadNet(net, builder);
81
// load the weights when wished/available
82
if (oc.isSet("weight-files")) {
83
loader.loadWeights(net, "weight-files", oc.getString("weight-attribute"), false, oc.getBool("weights.expand"));
84
}
85
if (oc.isSet("lane-weight-files")) {
86
loader.loadWeights(net, "lane-weight-files", oc.getString("weight-attribute"), true, oc.getBool("weights.expand"));
87
}
88
if (oc.getBool("skip-new-routes")) {
89
RORouteDef::setSkipNew();
90
}
91
}
92
93
94
/**
95
* Computes the routes saving them
96
*/
97
void
98
computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
99
// initialise the loader
100
loader.openRoutes(net);
101
// build the router
102
auto ttFunction = gWeightsRandomFactor > 1 ? &ROEdge::getTravelTimeStaticRandomized : &ROEdge::getTravelTimeStatic;
103
SUMOAbstractRouter<ROEdge, ROVehicle>* router;
104
const std::string measure = oc.getString("weight-attribute");
105
const std::string routingAlgorithm = oc.getString("routing-algorithm");
106
const double priorityFactor = oc.getFloat("weights.priority-factor");
107
const SUMOTime begin = string2time(oc.getString("begin"));
108
const SUMOTime end = oc.isDefault("end") ? SUMOTime_MAX : string2time(oc.getString("end"));
109
DijkstraRouter<ROEdge, ROVehicle>::Operation op = &ROEdge::getTravelTimeStatic;
110
111
if (oc.isSet("restriction-params") &&
112
(routingAlgorithm == "CH" || routingAlgorithm == "CHWrapper")) {
113
throw ProcessError(TLF("Routing algorithm '%' does not support restriction-params", routingAlgorithm));
114
}
115
116
if (measure == "traveltime" && priorityFactor == 0) {
117
if (routingAlgorithm == "dijkstra") {
118
router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, nullptr, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
119
} else if (routingAlgorithm == "astar") {
120
typedef AStarRouter<ROEdge, ROVehicle, ROMapMatcher> AStar;
121
std::shared_ptr<const AStar::LookupTable> lookup;
122
if (oc.isSet("astar.all-distances")) {
123
lookup = std::make_shared<const AStar::FLT>(oc.getString("astar.all-distances"), (int)ROEdge::getAllEdges().size());
124
} else if (oc.isSet("astar.landmark-distances")) {
125
/* CHRouterWrapper<ROEdge, ROVehicle> chrouter(
126
ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic,
127
begin, end, SUMOTime_MAX, 1); */
128
DijkstraRouter<ROEdge, ROVehicle> forward(ROEdge::getAllEdges(), true, &ROEdge::getTravelTimeStatic);
129
std::vector<ReversedEdge<ROEdge, ROVehicle>*> reversed;
130
for (ROEdge* edge : ROEdge::getAllEdges()) {
131
reversed.push_back(edge->getReversedRoutingEdge());
132
}
133
for (ReversedEdge<ROEdge, ROVehicle>* redge : reversed) {
134
redge->init();
135
}
136
DijkstraRouter<ReversedEdge<ROEdge, ROVehicle>, ROVehicle> backward(reversed, true, &ReversedEdge<ROEdge, ROVehicle>::getTravelTimeStatic);
137
ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
138
ROMapMatcher* mapMatcher = dynamic_cast<ROMapMatcher*>(loader.getRouteHandler());
139
lookup = std::make_shared<const AStar::LMLT>(oc.getString("astar.landmark-distances"), ROEdge::getAllEdges(), &forward, &backward, &defaultVehicle,
140
oc.isSet("astar.save-landmark-distances") ? oc.getString("astar.save-landmark-distances") : "", oc.getInt("routing-threads"), mapMatcher);
141
}
142
router = new AStar(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, lookup, net.hasPermissions(), oc.isSet("restriction-params"));
143
} else if (routingAlgorithm == "CH" && !net.hasPermissions()) {
144
const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
145
string2time(oc.getString("weight-period")) :
146
SUMOTime_MAX);
147
router = new CHRouter<ROEdge, ROVehicle>(
148
ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction, SVC_IGNORING, weightPeriod, net.hasPermissions(), oc.isSet("restriction-params"));
149
} else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
150
// use CHWrapper instead of CH if the net has permissions
151
const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
152
string2time(oc.getString("weight-period")) :
153
SUMOTime_MAX);
154
router = new CHRouterWrapper<ROEdge, ROVehicle>(
155
ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttFunction,
156
begin, end, weightPeriod, net.hasPermissions(), oc.getInt("routing-threads"));
157
} else if (routingAlgorithm == "arcflag") {
158
/// @brief The number of levels in the k-d tree partition
159
constexpr auto NUMBER_OF_LEVELS = 5; //or 4 or 8
160
ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
161
KDTreePartition<ROEdge, RONode, ROVehicle>* partition = new KDTreePartition<ROEdge, RONode, ROVehicle>(NUMBER_OF_LEVELS, ROEdge::getAllEdges(), net.hasPermissions(), oc.isSet("restriction-params"));
162
partition->init(&defaultVehicle);
163
auto reversedTtFunction = gWeightsRandomFactor > 1 ? &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStaticRandomized : &FlippedEdge<ROEdge, RONode, ROVehicle>::getTravelTimeStatic;
164
router = new AFRouter<ROEdge, RONode, ROVehicle, ROMapMatcher>(ROEdge::getAllEdges(),
165
partition, oc.getBool("ignore-errors"), ttFunction, reversedTtFunction, (oc.isSet("weight-files") ? string2time(oc.getString("weight-period")) : SUMOTime_MAX),
166
nullptr, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
167
} else {
168
throw ProcessError(TLF("Unknown routing Algorithm '%'!", routingAlgorithm));
169
}
170
} else {
171
if (measure == "traveltime") {
172
if (ROEdge::initPriorityFactor(priorityFactor)) {
173
op = &ROEdge::getTravelTimeStaticPriorityFactor;
174
}
175
} else if (measure == "CO") {
176
op = &ROEdge::getEmissionEffort<PollutantsInterface::CO>;
177
} else if (measure == "CO2") {
178
op = &ROEdge::getEmissionEffort<PollutantsInterface::CO2>;
179
} else if (measure == "PMx") {
180
op = &ROEdge::getEmissionEffort<PollutantsInterface::PM_X>;
181
} else if (measure == "HC") {
182
op = &ROEdge::getEmissionEffort<PollutantsInterface::HC>;
183
} else if (measure == "NOx") {
184
op = &ROEdge::getEmissionEffort<PollutantsInterface::NO_X>;
185
} else if (measure == "fuel") {
186
op = &ROEdge::getEmissionEffort<PollutantsInterface::FUEL>;
187
} else if (measure == "electricity") {
188
op = &ROEdge::getEmissionEffort<PollutantsInterface::ELEC>;
189
} else if (measure == "noise") {
190
op = &ROEdge::getNoiseEffort;
191
} else {
192
op = &ROEdge::getStoredEffort;
193
}
194
if (measure != "traveltime" && !net.hasLoadedEffort()) {
195
WRITE_WARNINGF(TL("No weight data was loaded for attribute '%'."), measure);
196
}
197
router = new DijkstraRouter<ROEdge, ROVehicle>(
198
ROEdge::getAllEdges(), oc.getBool("ignore-errors"), op, ttFunction, false, nullptr, net.hasPermissions(), oc.isSet("restriction-params"));
199
}
200
const int carWalk = SUMOVehicleParserHelper::parseCarWalkTransfer(oc, true);
201
double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
202
203
RailwayRouter<ROEdge, ROVehicle>* railRouter = nullptr;
204
if (net.hasBidiEdges()) {
205
railRouter = new RailwayRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), true, op, ttFunction, false, net.hasPermissions(),
206
oc.isSet("restriction-params"),
207
oc.getFloat("railway.max-train-length"),
208
oc.getFloat("weights.reversal-penalty"));
209
}
210
RORouterProvider provider(router, new PedestrianRouter<ROEdge, ROLane, RONode, ROVehicle>(),
211
new ROIntermodalRouter(RONet::adaptIntermodalRouter, carWalk, taxiWait, routingAlgorithm),
212
railRouter);
213
// process route definitions
214
try {
215
net.openOutput(oc);
216
loader.processRoutes(begin, end, string2time(oc.getString("route-steps")), net, provider);
217
net.writeIntermodal(oc, provider.getIntermodalRouter());
218
// end the processing
219
net.cleanup();
220
} catch (ProcessError&) {
221
net.cleanup();
222
throw;
223
}
224
}
225
226
227
/* -------------------------------------------------------------------------
228
* main
229
* ----------------------------------------------------------------------- */
230
int
231
main(int argc, char** argv) {
232
OptionsCont& oc = OptionsCont::getOptions();
233
oc.setApplicationDescription(TL("Shortest path router and DUE computer for the microscopic, multi-modal traffic simulation SUMO."));
234
oc.setApplicationName("duarouter", "Eclipse SUMO duarouter " VERSION_STRING);
235
int ret = 0;
236
RONet* net = nullptr;
237
try {
238
XMLSubSys::init();
239
RODUAFrame::fillOptions();
240
OptionsIO::setArgs(argc, argv);
241
OptionsIO::getOptions();
242
if (oc.processMetaOptions(argc < 2)) {
243
SystemFrame::close();
244
return 0;
245
}
246
SystemFrame::checkOptions(oc);
247
XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
248
#ifdef HAVE_FOX
249
if (oc.getInt("routing-threads") > 1) {
250
// make the output aware of threading
251
MsgHandler::setFactory(&MsgHandlerSynchronized::create);
252
}
253
#endif
254
MsgHandler::initOutputOptions();
255
if (!RODUAFrame::checkOptions()) {
256
throw ProcessError();
257
}
258
RandHelper::initRandGlobal();
259
// load data
260
ROLoader loader(oc, false, !oc.getBool("no-step-log"));
261
net = new RONet();
262
initNet(*net, loader, oc);
263
// build routes
264
try {
265
computeRoutes(*net, loader, oc);
266
} catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
267
WRITE_ERROR(toString(e.getLineNumber()));
268
ret = 1;
269
} catch (XERCES_CPP_NAMESPACE::SAXException& e) {
270
WRITE_ERROR(StringUtils::transcode(e.getMessage()));
271
ret = 1;
272
}
273
if (MsgHandler::getErrorInstance()->wasInformed() || ret != 0) {
274
throw ProcessError();
275
}
276
} catch (const ProcessError& e) {
277
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
278
WRITE_ERROR(e.what());
279
}
280
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
281
ret = 1;
282
#ifndef _DEBUG
283
} catch (const std::exception& e) {
284
if (std::string(e.what()) != std::string("")) {
285
WRITE_ERROR(e.what());
286
}
287
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
288
ret = 1;
289
} catch (...) {
290
MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
291
ret = 1;
292
#endif
293
}
294
delete net;
295
SystemFrame::close();
296
if (ret == 0) {
297
std::cout << "Success." << std::endl;
298
}
299
return ret;
300
}
301
302
303
/****************************************************************************/
304
305