Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 ROLoader.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @author Christian Roessel
20 : /// @date Sept 2002
21 : ///
22 : // Loader for networks and route imports
23 : /****************************************************************************/
24 : #include <config.h>
25 :
26 : #include <iostream>
27 : #include <string>
28 : #include <iomanip>
29 : #include <utils/options/OptionsCont.h>
30 : #include <utils/common/ToString.h>
31 : #include <utils/common/StringTokenizer.h>
32 : #include <utils/common/MsgHandler.h>
33 : #include <utils/common/UtilExceptions.h>
34 : #include <utils/common/FileHelpers.h>
35 : #include <utils/xml/XMLSubSys.h>
36 : #include <utils/xml/SAXWeightsHandler.h>
37 : #include <utils/vehicle/SUMORouteLoader.h>
38 : #include <utils/vehicle/SUMORouteLoaderControl.h>
39 : #include "RONet.h"
40 : #include "RONetHandler.h"
41 : #include "ROLoader.h"
42 : #include "ROLane.h"
43 : #include "ROEdge.h"
44 : #include "RORouteHandler.h"
45 :
46 :
47 : // ===========================================================================
48 : // method definitions
49 : // ===========================================================================
50 : // ---------------------------------------------------------------------------
51 : // ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime - methods
52 : // ---------------------------------------------------------------------------
53 : void
54 5617 : ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
55 : double val, double beg, double end) const {
56 5617 : ROEdge* e = myNet.getEdge(id);
57 5617 : if (e != nullptr) {
58 5617 : e->addTravelTime(val, beg, end);
59 : } else {
60 0 : if (id[0] != ':') {
61 0 : if (OptionsCont::getOptions().getBool("ignore-errors")) {
62 0 : WRITE_WARNINGF(TL("Trying to set a weight for the unknown edge '%'."), id);
63 : } else {
64 0 : WRITE_ERRORF(TL("Trying to set a weight for the unknown edge '%'."), id);
65 : }
66 : }
67 : }
68 5617 : }
69 :
70 :
71 : // ---------------------------------------------------------------------------
72 : // ROLoader::EdgeFloatTimeLineRetriever_EdgeWeight - methods
73 : // ---------------------------------------------------------------------------
74 : void
75 189 : ROLoader::EdgeFloatTimeLineRetriever_EdgeWeight::addEdgeWeight(const std::string& id,
76 : double val, double beg, double end) const {
77 189 : ROEdge* e = myNet.getEdge(id);
78 189 : if (e != nullptr) {
79 189 : e->addEffort(val, beg, end);
80 : } else {
81 0 : if (id[0] != ':') {
82 0 : if (OptionsCont::getOptions().getBool("ignore-errors")) {
83 0 : WRITE_WARNINGF(TL("Trying to set a weight for the unknown edge '%'."), id);
84 : } else {
85 0 : WRITE_ERRORF(TL("Trying to set a weight for the unknown edge '%'."), id);
86 : }
87 : }
88 : }
89 189 : }
90 :
91 :
92 : // ---------------------------------------------------------------------------
93 : // ROLoader - methods
94 : // ---------------------------------------------------------------------------
95 4240 : ROLoader::ROLoader(OptionsCont& oc, const bool emptyDestinationsAllowed, const bool logSteps) :
96 4240 : myOptions(oc),
97 4240 : myEmptyDestinationsAllowed(emptyDestinationsAllowed),
98 4240 : myLogSteps(logSteps),
99 7941 : myLoaders(oc.exists("unsorted-input") && oc.getBool("unsorted-input") ? 0 : DELTA_T) {
100 4240 : }
101 :
102 :
103 4240 : ROLoader::~ROLoader() {
104 4240 : }
105 :
106 :
107 : void
108 4240 : ROLoader::loadNet(RONet& toFill, ROAbstractEdgeBuilder& eb) {
109 4240 : std::string file = myOptions.getString("net-file");
110 4240 : if (file == "") {
111 14 : throw ProcessError(TL("Missing definition of network to load!"));
112 : }
113 8466 : if (!FileHelpers::isReadable(file)) {
114 24 : throw ProcessError(TLF("The network file '%' is not accessible.", file));
115 : }
116 8450 : PROGRESS_BEGIN_MESSAGE(TL("Loading net"));
117 12141 : RONetHandler handler(toFill, eb, !myOptions.exists("no-internal-links") || myOptions.getBool("no-internal-links"),
118 16030 : myOptions.exists("weights.minor-penalty") ? myOptions.getFloat("weights.minor-penalty") : 0,
119 16030 : myOptions.exists("weights.tls-penalty") ? myOptions.getFloat("weights.tls-penalty") : 0,
120 25636 : myOptions.exists("weights.turnaround-penalty") ? myOptions.getFloat("weights.turnaround-penalty") : 0);
121 4225 : handler.setFileName(file);
122 4225 : if (!XMLSubSys::runParser(handler, file, true)) {
123 702 : PROGRESS_FAILED_MESSAGE();
124 702 : throw ProcessError();
125 : } else {
126 3523 : PROGRESS_DONE_MESSAGE();
127 : }
128 3523 : if (!deprecatedVehicleClassesSeen.empty()) {
129 0 : WRITE_WARNINGF(TL("Deprecated vehicle classes '%' in input network."), toString(deprecatedVehicleClassesSeen));
130 : deprecatedVehicleClassesSeen.clear();
131 : }
132 7046 : if (myOptions.isSet("additional-files", false)) { // dfrouter does not register this option
133 1424 : std::vector<std::string> files = myOptions.getStringVector("additional-files");
134 1499 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
135 1582 : if (!FileHelpers::isReadable(*fileIt)) {
136 0 : throw ProcessError(TLF("The additional file '%' is not accessible.", *fileIt));
137 : }
138 2373 : PROGRESS_BEGIN_MESSAGE("Loading additional file '" + *fileIt + "' ");
139 791 : handler.setFileName(*fileIt);
140 791 : if (!XMLSubSys::runParser(handler, *fileIt)) {
141 4 : PROGRESS_FAILED_MESSAGE();
142 4 : throw ProcessError();
143 : } else {
144 787 : PROGRESS_DONE_MESSAGE();
145 : }
146 : }
147 712 : }
148 6837 : if (myOptions.exists("junction-taz") && myOptions.getBool("junction-taz")) {
149 : // create a TAZ for every junction
150 101 : toFill.addJunctionTaz(eb);
151 : }
152 3519 : toFill.setBidiEdges(handler.getBidiMap());
153 6837 : if (myOptions.exists("restriction-params") && myOptions.isSet("restriction-params")) {
154 : toFill.setParamRestrictions();
155 56 : const std::vector<std::string> paramKeys = myOptions.getStringVector("restriction-params");
156 436 : for (auto& edgeIt : toFill.getEdgeMap()) {
157 408 : edgeIt.second->cacheParamRestrictions(paramKeys);
158 : }
159 28 : }
160 3519 : if (toFill.hasSpeedRestrictions()) {
161 71 : for (auto& edgeIt : toFill.getEdgeMap()) {
162 66 : edgeIt.second->setSpeedRestrictions(toFill.getRestrictions(edgeIt.second->getType()));
163 : }
164 : }
165 7744 : }
166 :
167 :
168 : void
169 3212 : ROLoader::openRoutes(RONet& net) {
170 : // build loader
171 : // load relevant elements from additional file
172 3212 : bool ok = openTypedRoutes("additional-files", net, true);
173 : // load sumo routes, trips, and flows
174 3212 : ok &= openTypedRoutes("route-files", net);
175 : // check
176 3212 : if (ok) {
177 3195 : myLoaders.loadNext(string2time(myOptions.getString("begin")));
178 2818 : if (!net.furtherStored()) {
179 77 : if (MsgHandler::getErrorInstance()->wasInformed()) {
180 57 : throw ProcessError();
181 : } else {
182 20 : const std::string error = "No route input specified or all routes were invalid.";
183 40 : if (myOptions.getBool("ignore-errors")) {
184 42 : WRITE_WARNING(error);
185 : } else {
186 9 : throw ProcessError(error);
187 : }
188 : }
189 : }
190 : // skip routes prior to the begin time
191 5504 : if (!myOptions.getBool("unsorted-input")) {
192 8103 : WRITE_MESSAGE("Skipped until: " + time2string(myLoaders.getFirstLoadTime()));
193 : }
194 : }
195 2769 : }
196 :
197 :
198 : void
199 2746 : ROLoader::processRoutes(const SUMOTime start, const SUMOTime end, const SUMOTime increment,
200 : RONet& net, const RORouterProvider& provider) {
201 2746 : const SUMOTime absNo = end - start;
202 2746 : const bool endGiven = !OptionsCont::getOptions().isDefault("end");
203 : // skip routes that begin before the simulation's begin
204 : // loop till the end
205 : const SUMOTime firstStep = myLoaders.getFirstLoadTime();
206 : SUMOTime lastStep = firstStep;
207 : SUMOTime time = MIN2(firstStep, end);
208 19384 : while (time <= end) {
209 19384 : writeStats(time, start, absNo, endGiven);
210 19384 : myLoaders.loadNext(time);
211 19368 : if (!net.furtherStored() || MsgHandler::getErrorInstance()->wasInformed()) {
212 : break;
213 : }
214 19236 : lastStep = net.saveAndRemoveRoutesUntil(myOptions, provider, time);
215 19220 : if (time == end || (!net.furtherStored() && myLoaders.haveAllLoaded()) || MsgHandler::getErrorInstance()->wasInformed()) {
216 : break;
217 : }
218 16638 : if (time < end && time > end - increment) {
219 : time = end;
220 : } else {
221 16481 : time += increment;
222 : }
223 : }
224 2714 : if (myLogSteps) {
225 462 : WRITE_MESSAGEF(TL("Routes found between time steps % and %."), time2string(firstStep), time2string(lastStep));
226 : }
227 2714 : }
228 :
229 :
230 : bool
231 6424 : ROLoader::openTypedRoutes(const std::string& optionName,
232 : RONet& net, const bool readAll) {
233 : // check whether the current loader is wished
234 : // and the file(s) can be used
235 6424 : if (!myOptions.isUsableFileList(optionName)) {
236 2713 : return !myOptions.isSet(optionName);
237 : }
238 7513 : for (const std::string& fileIt : myOptions.getStringVector(optionName)) {
239 : try {
240 7604 : RORouteHandler* handler = new RORouteHandler(net, fileIt, myOptions.getBool("repair"), myEmptyDestinationsAllowed, myOptions.getBool("ignore-errors"), !readAll);
241 3802 : if (readAll) {
242 692 : if (!XMLSubSys::runParser(*handler, fileIt)) {
243 0 : WRITE_ERRORF(TL("Loading of % failed."), fileIt);
244 0 : return false;
245 : }
246 692 : delete handler;
247 : } else {
248 3110 : myLoaders.add(new SUMORouteLoader(handler));
249 : }
250 0 : } catch (ProcessError& e) {
251 0 : WRITE_ERRORF(TL("The loader for % from file '%' could not be initialised (%)."), optionName, fileIt, e.what());
252 : return false;
253 0 : }
254 : }
255 : return true;
256 : }
257 :
258 :
259 : bool
260 423 : ROLoader::loadWeights(RONet& net, const std::string& optionName,
261 : const std::string& measure, const bool useLanes, const bool boundariesOverride) {
262 : // check whether the file exists
263 423 : if (!myOptions.isUsableFileList(optionName)) {
264 : return false;
265 : }
266 : // build and prepare the weights handler
267 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
268 : // travel time, first (always used)
269 : EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(net);
270 846 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", !useLanes, ttRetriever));
271 : // the measure to use, then
272 : EdgeFloatTimeLineRetriever_EdgeWeight eRetriever(net);
273 423 : if (measure != "traveltime") {
274 : std::string umeasure = measure;
275 10 : if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
276 16 : umeasure = measure + "_perVeh";
277 : }
278 10 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(umeasure, !useLanes, eRetriever));
279 : }
280 : // set up handler
281 423 : SAXWeightsHandler handler(retrieverDefs, "");
282 : // go through files
283 423 : std::vector<std::string> files = myOptions.getStringVector(optionName);
284 850 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
285 1281 : PROGRESS_BEGIN_MESSAGE("Loading precomputed net weights from '" + *fileIt + "'");
286 427 : if (XMLSubSys::runParser(handler, *fileIt)) {
287 427 : PROGRESS_DONE_MESSAGE();
288 : } else {
289 0 : WRITE_MESSAGE(TL("failed."));
290 : return false;
291 : }
292 : }
293 : // build edge-internal time lines
294 6651 : for (const auto& i : net.getEdgeMap()) {
295 6228 : i.second->buildTimeLines(measure, boundariesOverride);
296 : }
297 : return true;
298 423 : }
299 :
300 :
301 : void
302 19384 : ROLoader::writeStats(const SUMOTime time, const SUMOTime start, const SUMOTime absNo, bool endGiven) {
303 19384 : if (myLogSteps) {
304 466 : if (endGiven) {
305 0 : const double perc = (double)(time - start) / (double) absNo;
306 0 : std::cout << "Reading up to time step: " + time2string(time) + " (" + time2string(time - start) + "/" + time2string(absNo) + " = " + toString(perc * 100) + "% done) \r";
307 : } else {
308 932 : std::cout << "Reading up to time step: " + time2string(time) + "\r";
309 : }
310 : }
311 19384 : }
312 :
313 : SUMORouteHandler*
314 20 : ROLoader::getRouteHandler() {
315 20 : auto loader = myLoaders.getFirstLoader();
316 20 : if (loader != nullptr) {
317 20 : return loader->getRouteHandler();
318 : } else {
319 : return nullptr;
320 : }
321 : }
322 : /****************************************************************************/
|