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