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 5262 : ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
55 : double val, double beg, double end) const {
56 5262 : ROEdge* e = myNet.getEdge(id);
57 5262 : if (e != nullptr) {
58 5262 : 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 5262 : }
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 10102 : ROLoader::ROLoader(OptionsCont& oc, const bool emptyDestinationsAllowed, const bool logSteps) :
96 10102 : myOptions(oc),
97 10102 : myEmptyDestinationsAllowed(emptyDestinationsAllowed),
98 10102 : myLogSteps(logSteps),
99 19666 : myLoaders(oc.exists("unsorted-input") && oc.getBool("unsorted-input") ? 0 : DELTA_T) {
100 10102 : }
101 :
102 :
103 10102 : ROLoader::~ROLoader() {
104 10102 : }
105 :
106 :
107 : void
108 10102 : ROLoader::loadNet(RONet& toFill, ROAbstractEdgeBuilder& eb) {
109 10102 : std::string file = myOptions.getString("net-file");
110 10102 : if (file == "") {
111 14 : throw ProcessError(TL("Missing definition of network to load!"));
112 : }
113 20190 : if (!FileHelpers::isReadable(file)) {
114 24 : throw ProcessError(TLF("The network file '%' is not accessible.", file));
115 : }
116 20174 : PROGRESS_BEGIN_MESSAGE(TL("Loading net"));
117 29728 : RONetHandler handler(toFill, eb, !myOptions.exists("no-internal-links") || myOptions.getBool("no-internal-links"),
118 39480 : myOptions.exists("weights.minor-penalty") ? myOptions.getFloat("weights.minor-penalty") : 0,
119 39480 : myOptions.exists("weights.tls-penalty") ? myOptions.getFloat("weights.tls-penalty") : 0,
120 60809 : myOptions.exists("weights.turnaround-penalty") ? myOptions.getFloat("weights.turnaround-penalty") : 0);
121 10087 : handler.setFileName(file);
122 10087 : if (!XMLSubSys::runParser(handler, file, true)) {
123 702 : PROGRESS_FAILED_MESSAGE();
124 702 : throw ProcessError();
125 : } else {
126 9385 : PROGRESS_DONE_MESSAGE();
127 : }
128 9385 : if (!deprecatedVehicleClassesSeen.empty()) {
129 0 : WRITE_WARNINGF(TL("Deprecated vehicle classes '%' in input network."), toString(deprecatedVehicleClassesSeen));
130 : deprecatedVehicleClassesSeen.clear();
131 : }
132 18770 : if (myOptions.isSet("additional-files", false)) { // dfrouter does not register this option
133 13576 : std::vector<std::string> files = myOptions.getStringVector("additional-files");
134 13645 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
135 13722 : if (!FileHelpers::isReadable(*fileIt)) {
136 0 : throw ProcessError(TLF("The additional file '%' is not accessible.", *fileIt));
137 : }
138 20583 : PROGRESS_BEGIN_MESSAGE("Loading additional file '" + *fileIt + "' ");
139 6861 : handler.setFileName(*fileIt);
140 6861 : if (!XMLSubSys::runParser(handler, *fileIt)) {
141 4 : PROGRESS_FAILED_MESSAGE();
142 4 : throw ProcessError();
143 : } else {
144 6857 : PROGRESS_DONE_MESSAGE();
145 : }
146 : }
147 6788 : }
148 18562 : if (myOptions.exists("junction-taz") && myOptions.getBool("junction-taz")) {
149 : // create a TAZ for every junction
150 91 : toFill.addJunctionTaz(eb);
151 : }
152 9381 : toFill.setBidiEdges(handler.getBidiMap());
153 18562 : if (myOptions.exists("restriction-params") && myOptions.isSet("restriction-params")) {
154 40 : const std::vector<std::string> paramKeys = myOptions.getStringVector("restriction-params");
155 316 : for (auto& edgeIt : toFill.getEdgeMap()) {
156 296 : edgeIt.second->cacheParamRestrictions(paramKeys);
157 : }
158 20 : }
159 9381 : if (toFill.hasRestrictions()) {
160 71 : for (auto& edgeIt : toFill.getEdgeMap()) {
161 66 : edgeIt.second->setRestrictions(toFill.getRestrictions(edgeIt.second->getType()));
162 : }
163 : }
164 19468 : }
165 :
166 :
167 : void
168 9075 : ROLoader::openRoutes(RONet& net) {
169 : // build loader
170 : // load relevant elements from additional file
171 9075 : bool ok = openTypedRoutes("additional-files", net, true);
172 : // load sumo routes, trips, and flows
173 9075 : ok &= openTypedRoutes("route-files", net);
174 : // check
175 9075 : if (ok) {
176 9058 : myLoaders.loadNext(string2time(myOptions.getString("begin")));
177 7145 : if (!net.furtherStored()) {
178 942 : if (MsgHandler::getErrorInstance()->wasInformed()) {
179 929 : throw ProcessError();
180 : } else {
181 13 : const std::string error = "No route input specified or all routes were invalid.";
182 26 : if (myOptions.getBool("ignore-errors")) {
183 21 : WRITE_WARNING(error);
184 : } else {
185 18 : throw ProcessError(error);
186 : }
187 : }
188 : }
189 : // skip routes prior to the begin time
190 12414 : if (!myOptions.getBool("unsorted-input")) {
191 18468 : WRITE_MESSAGE("Skipped until: " + time2string(myLoaders.getFirstLoadTime()));
192 : }
193 : }
194 6224 : }
195 :
196 :
197 : void
198 6205 : ROLoader::processRoutes(const SUMOTime start, const SUMOTime end, const SUMOTime increment,
199 : RONet& net, const RORouterProvider& provider) {
200 6205 : const SUMOTime absNo = end - start;
201 6205 : const bool endGiven = !OptionsCont::getOptions().isDefault("end");
202 : // skip routes that begin before the simulation's begin
203 : // loop till the end
204 : const SUMOTime firstStep = myLoaders.getFirstLoadTime();
205 : SUMOTime lastStep = firstStep;
206 : SUMOTime time = MIN2(firstStep, end);
207 25304 : while (time <= end) {
208 25304 : writeStats(time, start, absNo, endGiven);
209 25304 : myLoaders.loadNext(time);
210 25288 : if (!net.furtherStored() || MsgHandler::getErrorInstance()->wasInformed()) {
211 : break;
212 : }
213 25163 : lastStep = net.saveAndRemoveRoutesUntil(myOptions, provider, time);
214 25147 : if (time == end || (!net.furtherStored() && myLoaders.haveAllLoaded()) || MsgHandler::getErrorInstance()->wasInformed()) {
215 : break;
216 : }
217 19099 : if (time < end && time > end - increment) {
218 : time = end;
219 : } else {
220 19041 : time += increment;
221 : }
222 : }
223 6173 : if (myLogSteps) {
224 432 : WRITE_MESSAGEF(TL("Routes found between time steps % and %."), time2string(firstStep), time2string(lastStep));
225 : }
226 6173 : }
227 :
228 :
229 : bool
230 18150 : ROLoader::openTypedRoutes(const std::string& optionName,
231 : RONet& net, const bool readAll) {
232 : // check whether the current loader is wished
233 : // and the file(s) can be used
234 18150 : if (!myOptions.isUsableFileList(optionName)) {
235 2500 : return !myOptions.isSet(optionName);
236 : }
237 31385 : for (const std::string& fileIt : myOptions.getStringVector(optionName)) {
238 : try {
239 31470 : RORouteHandler* handler = new RORouteHandler(net, fileIt, myOptions.getBool("repair"), myEmptyDestinationsAllowed, myOptions.getBool("ignore-errors"), !readAll);
240 15735 : if (readAll) {
241 6762 : if (!XMLSubSys::runParser(*handler, fileIt)) {
242 0 : WRITE_ERRORF(TL("Loading of % failed."), fileIt);
243 0 : return false;
244 : }
245 6762 : delete handler;
246 : } else {
247 8973 : myLoaders.add(new SUMORouteLoader(handler));
248 : }
249 0 : } catch (ProcessError& e) {
250 0 : WRITE_ERRORF(TL("The loader for % from file '%' could not be initialised (%)."), optionName, fileIt, e.what());
251 : return false;
252 0 : }
253 : }
254 : return true;
255 : }
256 :
257 :
258 : bool
259 408 : ROLoader::loadWeights(RONet& net, const std::string& optionName,
260 : const std::string& measure, const bool useLanes, const bool boundariesOverride) {
261 : // check whether the file exists
262 408 : if (!myOptions.isUsableFileList(optionName)) {
263 : return false;
264 : }
265 : // build and prepare the weights handler
266 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
267 : // travel time, first (always used)
268 : EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(net);
269 816 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", !useLanes, ttRetriever));
270 : // the measure to use, then
271 : EdgeFloatTimeLineRetriever_EdgeWeight eRetriever(net);
272 408 : if (measure != "traveltime") {
273 : std::string umeasure = measure;
274 10 : if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
275 16 : umeasure = measure + "_perVeh";
276 : }
277 10 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(umeasure, !useLanes, eRetriever));
278 : }
279 : // set up handler
280 408 : SAXWeightsHandler handler(retrieverDefs, "");
281 : // go through files
282 408 : std::vector<std::string> files = myOptions.getStringVector(optionName);
283 820 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
284 1236 : PROGRESS_BEGIN_MESSAGE("Loading precomputed net weights from '" + *fileIt + "'");
285 412 : if (XMLSubSys::runParser(handler, *fileIt)) {
286 412 : PROGRESS_DONE_MESSAGE();
287 : } else {
288 0 : WRITE_MESSAGE(TL("failed."));
289 : return false;
290 : }
291 : }
292 : // build edge-internal time lines
293 5523 : for (const auto& i : net.getEdgeMap()) {
294 5115 : i.second->buildTimeLines(measure, boundariesOverride);
295 : }
296 : return true;
297 408 : }
298 :
299 :
300 : void
301 25304 : ROLoader::writeStats(const SUMOTime time, const SUMOTime start, const SUMOTime absNo, bool endGiven) {
302 25304 : if (myLogSteps) {
303 437 : if (endGiven) {
304 0 : const double perc = (double)(time - start) / (double) absNo;
305 0 : std::cout << "Reading up to time step: " + time2string(time) + " (" + time2string(time - start) + "/" + time2string(absNo) + " = " + toString(perc * 100) + "% done) \r";
306 : } else {
307 874 : std::cout << "Reading up to time step: " + time2string(time) + "\r";
308 : }
309 : }
310 25304 : }
311 :
312 : SUMORouteHandler*
313 20 : ROLoader::getRouteHandler() {
314 20 : auto loader = myLoaders.getFirstLoader();
315 20 : if (loader != nullptr) {
316 20 : return loader->getRouteHandler();
317 : } else {
318 : return nullptr;
319 : }
320 : }
321 : /****************************************************************************/
|