1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    ROLoader.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Sascha Krieg
14 /// @author  Michael Behrisch
15 /// @author  Christian Roessel
16 /// @date    Sept 2002
17 /// @version $Id$
18 ///
19 // Loader for networks and route imports
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <iostream>
29 #include <string>
30 #include <iomanip>
31 #include <xercesc/parsers/SAXParser.hpp>
32 #include <xercesc/util/PlatformUtils.hpp>
33 #include <xercesc/util/TransService.hpp>
34 #include <xercesc/sax2/SAX2XMLReader.hpp>
35 #include <utils/options/OptionsCont.h>
36 #include <utils/common/ToString.h>
37 #include <utils/common/StringTokenizer.h>
38 #include <utils/common/MsgHandler.h>
39 #include <utils/common/UtilExceptions.h>
40 #include <utils/common/FileHelpers.h>
41 #include <utils/xml/XMLSubSys.h>
42 #include <utils/xml/SAXWeightsHandler.h>
43 #include <utils/vehicle/SUMORouteLoader.h>
44 #include <utils/vehicle/SUMORouteLoaderControl.h>
45 #include "RONet.h"
46 #include "RONetHandler.h"
47 #include "ROLoader.h"
48 #include "ROLane.h"
49 #include "ROEdge.h"
50 #include "RORouteHandler.h"
51 
52 
53 // ===========================================================================
54 // method definitions
55 // ===========================================================================
56 // ---------------------------------------------------------------------------
57 // ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime - methods
58 // ---------------------------------------------------------------------------
59 void
addEdgeWeight(const std::string & id,double val,double beg,double end) const60 ROLoader::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
61         double val, double beg, double end) const {
62     ROEdge* e = myNet.getEdge(id);
63     if (e != nullptr) {
64         e->addTravelTime(val, beg, end);
65     } else {
66         if (id[0] != ':') {
67             if (OptionsCont::getOptions().getBool("ignore-errors")) {
68                 WRITE_WARNING("Trying to set a weight for the unknown edge '" + id + "'.");
69             } else {
70                 WRITE_ERROR("Trying to set a weight for the unknown edge '" + id + "'.");
71             }
72         }
73     }
74 }
75 
76 
77 // ---------------------------------------------------------------------------
78 // ROLoader::EdgeFloatTimeLineRetriever_EdgeWeight - methods
79 // ---------------------------------------------------------------------------
80 void
addEdgeWeight(const std::string & id,double val,double beg,double end) const81 ROLoader::EdgeFloatTimeLineRetriever_EdgeWeight::addEdgeWeight(const std::string& id,
82         double val, double beg, double end) const {
83     ROEdge* e = myNet.getEdge(id);
84     if (e != nullptr) {
85         e->addEffort(val, beg, end);
86     } else {
87         if (id[0] != ':') {
88             if (OptionsCont::getOptions().getBool("ignore-errors")) {
89                 WRITE_WARNING("Trying to set a weight for the unknown edge '" + id + "'.");
90             } else {
91                 WRITE_ERROR("Trying to set a weight for the unknown edge '" + id + "'.");
92             }
93         }
94     }
95 }
96 
97 
98 // ---------------------------------------------------------------------------
99 // ROLoader - methods
100 // ---------------------------------------------------------------------------
ROLoader(OptionsCont & oc,const bool emptyDestinationsAllowed,const bool logSteps)101 ROLoader::ROLoader(OptionsCont& oc, const bool emptyDestinationsAllowed, const bool logSteps) :
102     myOptions(oc),
103     myEmptyDestinationsAllowed(emptyDestinationsAllowed),
104     myLogSteps(logSteps),
105     myLoaders(oc.exists("unsorted-input") && oc.getBool("unsorted-input") ? 0 : DELTA_T) {
106 }
107 
108 
~ROLoader()109 ROLoader::~ROLoader() {
110 }
111 
112 
113 void
loadNet(RONet & toFill,ROAbstractEdgeBuilder & eb)114 ROLoader::loadNet(RONet& toFill, ROAbstractEdgeBuilder& eb) {
115     std::string file = myOptions.getString("net-file");
116     if (file == "") {
117         throw ProcessError("Missing definition of network to load!");
118     }
119     if (!FileHelpers::isReadable(file)) {
120         throw ProcessError("The network file '" + file + "' is not accessible.");
121     }
122     PROGRESS_BEGIN_MESSAGE("Loading net");
123     RONetHandler handler(toFill, eb, !myOptions.exists("no-internal-links") || myOptions.getBool("no-internal-links"),
124                          myOptions.exists("weights.minor-penalty") ? myOptions.getFloat("weights.minor-penalty") : 0);
125     handler.setFileName(file);
126     if (!XMLSubSys::runParser(handler, file, true)) {
127         PROGRESS_FAILED_MESSAGE();
128         throw ProcessError();
129     } else {
130         PROGRESS_DONE_MESSAGE();
131     }
132     if (!deprecatedVehicleClassesSeen.empty()) {
133         WRITE_WARNING("Deprecated vehicle classes '" + toString(deprecatedVehicleClassesSeen) + "' in input network.");
134         deprecatedVehicleClassesSeen.clear();
135     }
136     if (myOptions.isSet("additional-files", false)) { // dfrouter does not register this option
137         std::vector<std::string> files = myOptions.getStringVector("additional-files");
138         for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
139             if (!FileHelpers::isReadable(*fileIt)) {
140                 throw ProcessError("The additional file '" + *fileIt + "' is not accessible.");
141             }
142             PROGRESS_BEGIN_MESSAGE("Loading additional file '" + *fileIt + "' ");
143             handler.setFileName(*fileIt);
144             if (!XMLSubSys::runParser(handler, *fileIt)) {
145                 PROGRESS_FAILED_MESSAGE();
146                 throw ProcessError();
147             } else {
148                 PROGRESS_DONE_MESSAGE();
149             }
150         }
151     }
152 }
153 
154 
155 void
openRoutes(RONet & net)156 ROLoader::openRoutes(RONet& net) {
157     // build loader
158     // load relevant elements from additional file
159     bool ok = openTypedRoutes("additional-files", net, true);
160     // load sumo routes, trips, and flows
161     ok &= openTypedRoutes("route-files", net);
162     // check
163     if (ok) {
164         myLoaders.loadNext(string2time(myOptions.getString("begin")));
165         if (!net.furtherStored()) {
166             if (MsgHandler::getErrorInstance()->wasInformed()) {
167                 throw ProcessError();
168             } else {
169                 const std::string error = "No route input specified or all routes were invalid.";
170                 if (myOptions.getBool("ignore-errors")) {
171                     WRITE_WARNING(error);
172                 } else {
173                     throw ProcessError(error);
174                 }
175             }
176         }
177         // skip routes prior to the begin time
178         if (!myOptions.getBool("unsorted-input")) {
179             WRITE_MESSAGE("Skipped until: " + time2string(myLoaders.getFirstLoadTime()));
180         }
181     }
182 }
183 
184 
185 void
processRoutes(const SUMOTime start,const SUMOTime end,const SUMOTime increment,RONet & net,const RORouterProvider & provider)186 ROLoader::processRoutes(const SUMOTime start, const SUMOTime end, const SUMOTime increment,
187                         RONet& net, const RORouterProvider& provider) {
188     const SUMOTime absNo = end - start;
189     const bool endGiven = !OptionsCont::getOptions().isDefault("end");
190     // skip routes that begin before the simulation's begin
191     // loop till the end
192     const SUMOTime firstStep = myLoaders.getFirstLoadTime();
193     SUMOTime lastStep = firstStep;
194     SUMOTime time = MIN2(firstStep, end);
195     while (time <= end) {
196         writeStats(time, start, absNo, endGiven);
197         myLoaders.loadNext(time);
198         if (!net.furtherStored() || MsgHandler::getErrorInstance()->wasInformed()) {
199             break;
200         }
201         lastStep = net.saveAndRemoveRoutesUntil(myOptions, provider, time);
202         if ((!net.furtherStored() && myLoaders.haveAllLoaded()) || MsgHandler::getErrorInstance()->wasInformed()) {
203             break;
204         }
205         if (time < end && time + increment > end) {
206             time = end;
207         } else {
208             time += increment;
209         }
210     }
211     if (myLogSteps) {
212         WRITE_MESSAGE("Routes found between time steps " + time2string(firstStep) + " and " + time2string(lastStep) + ".");
213     }
214 }
215 
216 
217 bool
openTypedRoutes(const std::string & optionName,RONet & net,const bool readAll)218 ROLoader::openTypedRoutes(const std::string& optionName,
219                           RONet& net, const bool readAll) {
220     // check whether the current loader is wished
221     //  and the file(s) can be used
222     if (!myOptions.isUsableFileList(optionName)) {
223         return !myOptions.isSet(optionName);
224     }
225     for (const std::string& fileIt : myOptions.getStringVector(optionName)) {
226         try {
227             RORouteHandler* handler = new RORouteHandler(net, fileIt, myOptions.getBool("repair"), myEmptyDestinationsAllowed, myOptions.getBool("ignore-errors"), !readAll);
228             if (readAll) {
229                 if (!XMLSubSys::runParser(*handler, fileIt)) {
230                     WRITE_ERROR("Loading of " + fileIt + " failed.");
231                     return false;
232                 }
233                 delete handler;
234             } else {
235                 myLoaders.add(new SUMORouteLoader(handler));
236             }
237         } catch (ProcessError& e) {
238             WRITE_ERROR("The loader for " + optionName + " from file '" + fileIt + "' could not be initialised (" + e.what() + ").");
239             return false;
240         }
241     }
242     return true;
243 }
244 
245 
246 bool
loadWeights(RONet & net,const std::string & optionName,const std::string & measure,const bool useLanes,const bool boundariesOverride)247 ROLoader::loadWeights(RONet& net, const std::string& optionName,
248                       const std::string& measure, const bool useLanes, const bool boundariesOverride) {
249     // check whether the file exists
250     if (!myOptions.isUsableFileList(optionName)) {
251         return false;
252     }
253     // build and prepare the weights handler
254     std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
255     //  travel time, first (always used)
256     EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(net);
257     retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", !useLanes, ttRetriever));
258     //  the measure to use, then
259     EdgeFloatTimeLineRetriever_EdgeWeight eRetriever(net);
260     if (measure != "traveltime") {
261         std::string umeasure = measure;
262         if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
263             umeasure = measure + "_perVeh";
264         }
265         retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(umeasure, !useLanes, eRetriever));
266     }
267     //  set up handler
268     SAXWeightsHandler handler(retrieverDefs, "");
269     // go through files
270     std::vector<std::string> files = myOptions.getStringVector(optionName);
271     for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
272         PROGRESS_BEGIN_MESSAGE("Loading precomputed net weights from '" + *fileIt + "'");
273         if (XMLSubSys::runParser(handler, *fileIt)) {
274             PROGRESS_DONE_MESSAGE();
275         } else {
276             WRITE_MESSAGE("failed.");
277             return false;
278         }
279     }
280     // build edge-internal time lines
281     for (const auto& i : net.getEdgeMap()) {
282         i.second->buildTimeLines(measure, boundariesOverride);
283     }
284     return true;
285 }
286 
287 
288 void
writeStats(const SUMOTime time,const SUMOTime start,const SUMOTime absNo,bool endGiven)289 ROLoader::writeStats(const SUMOTime time, const SUMOTime start, const SUMOTime absNo, bool endGiven) {
290     if (myLogSteps) {
291         if (endGiven) {
292             const double perc = (double)(time - start) / (double) absNo;
293             std::cout << "Reading up to time step: " + time2string(time) + "  (" + time2string(time - start) + "/" + time2string(absNo) + " = " + toString(perc * 100) + "% done)       \r";
294         } else {
295             std::cout << "Reading up to time step: " + time2string(time) + "\r";
296         }
297     }
298 }
299 
300 
301 /****************************************************************************/
302 
303