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 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 5216 : ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
55 : double val, double beg, double end) const {
56 5216 : ROEdge* e = myNet.getEdge(id);
57 5216 : if (e != nullptr) {
58 5216 : 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 5216 : }
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 9972 : ROLoader::ROLoader(OptionsCont& oc, const bool emptyDestinationsAllowed, const bool logSteps) :
96 9972 : myOptions(oc),
97 9972 : myEmptyDestinationsAllowed(emptyDestinationsAllowed),
98 9972 : myLogSteps(logSteps),
99 19414 : myLoaders(oc.exists("unsorted-input") && oc.getBool("unsorted-input") ? 0 : DELTA_T) {
100 9972 : }
101 :
102 :
103 9972 : ROLoader::~ROLoader() {
104 9972 : }
105 :
106 :
107 : void
108 9972 : ROLoader::loadNet(RONet& toFill, ROAbstractEdgeBuilder& eb) {
109 9972 : std::string file = myOptions.getString("net-file");
110 9972 : if (file == "") {
111 14 : throw ProcessError(TL("Missing definition of network to load!"));
112 : }
113 19930 : if (!FileHelpers::isReadable(file)) {
114 24 : throw ProcessError(TLF("The network file '%' is not accessible.", file));
115 : }
116 19914 : PROGRESS_BEGIN_MESSAGE(TL("Loading net"));
117 29346 : RONetHandler handler(toFill, eb, !myOptions.exists("no-internal-links") || myOptions.getBool("no-internal-links"),
118 38960 : myOptions.exists("weights.minor-penalty") ? myOptions.getFloat("weights.minor-penalty") : 0,
119 38960 : myOptions.exists("weights.tls-penalty") ? myOptions.getFloat("weights.tls-penalty") : 0,
120 60029 : myOptions.exists("weights.turnaround-penalty") ? myOptions.getFloat("weights.turnaround-penalty") : 0);
121 9957 : handler.setFileName(file);
122 9957 : if (!XMLSubSys::runParser(handler, file, true)) {
123 702 : PROGRESS_FAILED_MESSAGE();
124 702 : throw ProcessError();
125 : } else {
126 9255 : PROGRESS_DONE_MESSAGE();
127 : }
128 18310 : if (myOptions.exists("restriction-params") && myOptions.isSet("restriction-params")) {
129 32 : const std::vector<std::string> paramKeys = myOptions.getStringVector("restriction-params");
130 240 : for (auto& edgeIt : toFill.getEdgeMap()) {
131 224 : edgeIt.second->cacheParamRestrictions(paramKeys);
132 : }
133 16 : }
134 9255 : if (!deprecatedVehicleClassesSeen.empty()) {
135 0 : WRITE_WARNINGF(TL("Deprecated vehicle classes '%' in input network."), toString(deprecatedVehicleClassesSeen));
136 : deprecatedVehicleClassesSeen.clear();
137 : }
138 18510 : if (myOptions.isSet("additional-files", false)) { // dfrouter does not register this option
139 13498 : std::vector<std::string> files = myOptions.getStringVector("additional-files");
140 13567 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
141 13644 : if (!FileHelpers::isReadable(*fileIt)) {
142 0 : throw ProcessError(TLF("The additional file '%' is not accessible.", *fileIt));
143 : }
144 20466 : PROGRESS_BEGIN_MESSAGE("Loading additional file '" + *fileIt + "' ");
145 6822 : handler.setFileName(*fileIt);
146 6822 : if (!XMLSubSys::runParser(handler, *fileIt)) {
147 4 : PROGRESS_FAILED_MESSAGE();
148 4 : throw ProcessError();
149 : } else {
150 6818 : PROGRESS_DONE_MESSAGE();
151 : }
152 : }
153 6749 : }
154 18302 : if (myOptions.exists("junction-taz") && myOptions.getBool("junction-taz")) {
155 : // create a TAZ for every junction
156 77 : toFill.addJunctionTaz(eb);
157 : }
158 9251 : toFill.setBidiEdges(handler.getBidiMap());
159 19208 : }
160 :
161 :
162 : void
163 8953 : ROLoader::openRoutes(RONet& net) {
164 : // build loader
165 : // load relevant elements from additional file
166 8953 : bool ok = openTypedRoutes("additional-files", net, true);
167 : // load sumo routes, trips, and flows
168 8953 : ok &= openTypedRoutes("route-files", net);
169 : // check
170 8953 : if (ok) {
171 8936 : myLoaders.loadNext(string2time(myOptions.getString("begin")));
172 7023 : if (!net.furtherStored()) {
173 942 : if (MsgHandler::getErrorInstance()->wasInformed()) {
174 929 : throw ProcessError();
175 : } else {
176 13 : const std::string error = "No route input specified or all routes were invalid.";
177 26 : if (myOptions.getBool("ignore-errors")) {
178 21 : WRITE_WARNING(error);
179 : } else {
180 18 : throw ProcessError(error);
181 : }
182 : }
183 : }
184 : // skip routes prior to the begin time
185 12170 : if (!myOptions.getBool("unsorted-input")) {
186 18102 : WRITE_MESSAGE("Skipped until: " + time2string(myLoaders.getFirstLoadTime()));
187 : }
188 : }
189 6102 : }
190 :
191 :
192 : void
193 6089 : ROLoader::processRoutes(const SUMOTime start, const SUMOTime end, const SUMOTime increment,
194 : RONet& net, const RORouterProvider& provider) {
195 6089 : const SUMOTime absNo = end - start;
196 6089 : const bool endGiven = !OptionsCont::getOptions().isDefault("end");
197 : // skip routes that begin before the simulation's begin
198 : // loop till the end
199 : const SUMOTime firstStep = myLoaders.getFirstLoadTime();
200 : SUMOTime lastStep = firstStep;
201 : SUMOTime time = MIN2(firstStep, end);
202 24937 : while (time <= end) {
203 24937 : writeStats(time, start, absNo, endGiven);
204 24937 : myLoaders.loadNext(time);
205 24921 : if (!net.furtherStored() || MsgHandler::getErrorInstance()->wasInformed()) {
206 : break;
207 : }
208 24796 : lastStep = net.saveAndRemoveRoutesUntil(myOptions, provider, time);
209 24780 : if (time == end || (!net.furtherStored() && myLoaders.haveAllLoaded()) || MsgHandler::getErrorInstance()->wasInformed()) {
210 : break;
211 : }
212 18848 : if (time < end && time > end - increment) {
213 : time = end;
214 : } else {
215 18810 : time += increment;
216 : }
217 : }
218 6057 : if (myLogSteps) {
219 428 : WRITE_MESSAGEF(TL("Routes found between time steps % and %."), time2string(firstStep), time2string(lastStep));
220 : }
221 6057 : }
222 :
223 :
224 : bool
225 17906 : ROLoader::openTypedRoutes(const std::string& optionName,
226 : RONet& net, const bool readAll) {
227 : // check whether the current loader is wished
228 : // and the file(s) can be used
229 17906 : if (!myOptions.isUsableFileList(optionName)) {
230 2412 : return !myOptions.isSet(optionName);
231 : }
232 31073 : for (const std::string& fileIt : myOptions.getStringVector(optionName)) {
233 : try {
234 31158 : RORouteHandler* handler = new RORouteHandler(net, fileIt, myOptions.getBool("repair"), myEmptyDestinationsAllowed, myOptions.getBool("ignore-errors"), !readAll);
235 15579 : if (readAll) {
236 6728 : if (!XMLSubSys::runParser(*handler, fileIt)) {
237 0 : WRITE_ERRORF(TL("Loading of % failed."), fileIt);
238 0 : return false;
239 : }
240 6728 : delete handler;
241 : } else {
242 8851 : myLoaders.add(new SUMORouteLoader(handler));
243 : }
244 0 : } catch (ProcessError& e) {
245 0 : WRITE_ERRORF(TL("The loader for % from file '%' could not be initialised (%)."), optionName, fileIt, e.what());
246 : return false;
247 0 : }
248 : }
249 : return true;
250 : }
251 :
252 :
253 : bool
254 395 : ROLoader::loadWeights(RONet& net, const std::string& optionName,
255 : const std::string& measure, const bool useLanes, const bool boundariesOverride) {
256 : // check whether the file exists
257 395 : if (!myOptions.isUsableFileList(optionName)) {
258 : return false;
259 : }
260 : // build and prepare the weights handler
261 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
262 : // travel time, first (always used)
263 : EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(net);
264 790 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", !useLanes, ttRetriever));
265 : // the measure to use, then
266 : EdgeFloatTimeLineRetriever_EdgeWeight eRetriever(net);
267 395 : if (measure != "traveltime") {
268 : std::string umeasure = measure;
269 10 : if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
270 16 : umeasure = measure + "_perVeh";
271 : }
272 10 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(umeasure, !useLanes, eRetriever));
273 : }
274 : // set up handler
275 395 : SAXWeightsHandler handler(retrieverDefs, "");
276 : // go through files
277 395 : std::vector<std::string> files = myOptions.getStringVector(optionName);
278 794 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
279 1197 : PROGRESS_BEGIN_MESSAGE("Loading precomputed net weights from '" + *fileIt + "'");
280 399 : if (XMLSubSys::runParser(handler, *fileIt)) {
281 399 : PROGRESS_DONE_MESSAGE();
282 : } else {
283 0 : WRITE_MESSAGE(TL("failed."));
284 : return false;
285 : }
286 : }
287 : // build edge-internal time lines
288 5287 : for (const auto& i : net.getEdgeMap()) {
289 4892 : i.second->buildTimeLines(measure, boundariesOverride);
290 : }
291 : return true;
292 395 : }
293 :
294 :
295 : void
296 24937 : ROLoader::writeStats(const SUMOTime time, const SUMOTime start, const SUMOTime absNo, bool endGiven) {
297 24937 : if (myLogSteps) {
298 432 : if (endGiven) {
299 0 : const double perc = (double)(time - start) / (double) absNo;
300 0 : std::cout << "Reading up to time step: " + time2string(time) + " (" + time2string(time - start) + "/" + time2string(absNo) + " = " + toString(perc * 100) + "% done) \r";
301 : } else {
302 864 : std::cout << "Reading up to time step: " + time2string(time) + "\r";
303 : }
304 : }
305 24937 : }
306 :
307 :
308 : /****************************************************************************/
|