Eclipse SUMO - Simulation of Urban MObility
dfrouter_main.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 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 /****************************************************************************/
23 // Main for the DFROUTER
24 /****************************************************************************/
25 #include <config.h>
26 
27 #ifdef HAVE_VERSION_H
28 #include <version.h>
29 #endif
30 
31 #include <iostream>
32 #include <string>
33 #include <limits.h>
34 #include <ctime>
35 #include <xercesc/sax/SAXException.hpp>
36 #include <xercesc/sax/SAXParseException.hpp>
41 #include <utils/common/ToString.h>
43 #include <utils/options/Option.h>
47 #include <utils/xml/XMLSubSys.h>
48 #include <router/ROLoader.h>
49 #include <router/RONet.h>
50 #include "RODFEdgeBuilder.h"
51 #include "RODFFrame.h"
52 #include "RODFNet.h"
53 #include "RODFEdge.h"
54 #include "RODFDetector.h"
55 #include "RODFDetectorHandler.h"
56 #include "RODFRouteCont.h"
57 #include "RODFDetectorFlow.h"
58 #include "RODFDetFlowLoader.h"
59 
60 
61 // ===========================================================================
62 // functions
63 // ===========================================================================
64 /* -------------------------------------------------------------------------
65  * data processing methods
66  * ----------------------------------------------------------------------- */
67 void
68 readDetectors(RODFDetectorCon& detectors, OptionsCont& oc, RODFNet* optNet) {
69  if (!oc.isSet("detector-files")) {
70  throw ProcessError("No detector file given (use --detector-files <FILE>).");
71  }
72  // read definitions stored in XML-format
73  std::vector<std::string> files = oc.getStringVector("detector-files");
74  for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
75  if (!FileHelpers::isReadable(*fileIt)) {
76  throw ProcessError("Could not open detector file '" + *fileIt + "'");
77  }
78  PROGRESS_BEGIN_MESSAGE("Loading detector definitions from '" + *fileIt + "'");
79  RODFDetectorHandler handler(optNet, oc.getBool("ignore-invalid-detectors"), detectors, *fileIt);
80  if (XMLSubSys::runParser(handler, *fileIt)) {
82  } else {
84  throw ProcessError();
85  }
86  }
87  if (detectors.getDetectors().empty()) {
88  throw ProcessError("No detectors found.");
89  }
90 }
91 
92 
93 void
95  if (!oc.isSet("measure-files")) {
96  // ok, not given, return an empty container
97  return;
98  }
99  // check whether the file exists
100  std::vector<std::string> files = oc.getStringVector("measure-files");
101  for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
102  if (!FileHelpers::isReadable(*fileIt)) {
103  throw ProcessError("The measure-file '" + *fileIt + "' can not be opened.");
104  }
105  // parse
106  PROGRESS_BEGIN_MESSAGE("Loading flows from '" + *fileIt + "'");
107  RODFDetFlowLoader dfl(dc, flows, string2time(oc.getString("begin")), string2time(oc.getString("end")),
108  string2time(oc.getString("time-offset")), string2time(oc.getString("time-factor")));
109  dfl.read(*fileIt);
111  }
112 }
113 
114 
115 void
117  if (oc.getBool("print-absolute-flows")) {
118  flows.printAbsolute();
119  }
120 
121  // if a network was loaded... (mode1)
122  if (optNet != nullptr) {
123  if (oc.getBool("remove-empty-detectors")) {
124  PROGRESS_BEGIN_MESSAGE("Removing empty detectors");
125  optNet->removeEmptyDetectors(detectors, flows);
127  } else if (oc.getBool("report-empty-detectors")) {
128  PROGRESS_BEGIN_MESSAGE("Scanning for empty detectors");
129  optNet->reportEmptyDetectors(detectors, flows);
131  }
132  // compute the detector types (optionally)
133  if (!detectors.detectorsHaveCompleteTypes() || oc.getBool("revalidate-detectors")) {
134  optNet->computeTypes(detectors, oc.getBool("strict-sources"));
135  }
136  std::vector<RODFDetector*>::const_iterator i = detectors.getDetectors().begin();
137  for (; i != detectors.getDetectors().end(); ++i) {
138  if ((*i)->getType() == SOURCE_DETECTOR) {
139  break;
140  }
141  }
142  if (i == detectors.getDetectors().end() && !oc.getBool("routes-for-all")) {
143  throw ProcessError("No source detectors found.");
144  }
145  // compute routes between the detectors (optionally)
146  if (!detectors.detectorsHaveRoutes() || oc.getBool("revalidate-routes") || oc.getBool("guess-empty-flows")) {
147  PROGRESS_BEGIN_MESSAGE("Computing routes");
148  optNet->buildRoutes(detectors,
149  oc.getBool("keep-unfinished-routes"), oc.getBool("routes-for-all"),
150  !oc.getBool("keep-longer-routes"), oc.getInt("max-search-depth"));
152  }
153  }
154 
155  // check
156  // whether the detectors are valid
157  if (!detectors.detectorsHaveCompleteTypes()) {
158  throw ProcessError("The detector types are not defined; use in combination with a network");
159  }
160  // whether the detectors have routes
161  if (!detectors.detectorsHaveRoutes()) {
162  throw ProcessError("The emitters have no routes; use in combination with a network");
163  }
164 
165  // save the detectors if wished
166  if (oc.isSet("detector-output")) {
167  detectors.save(oc.getString("detector-output"));
168  }
169  // save their positions as POIs if wished
170  if (oc.isSet("detectors-poi-output")) {
171  detectors.saveAsPOIs(oc.getString("detectors-poi-output"));
172  }
173 
174  // save the routes file if it was changed or it's wished
175  if (detectors.detectorsHaveRoutes() && oc.isSet("routes-output")) {
176  detectors.saveRoutes(oc.getString("routes-output"));
177  }
178 
179  // guess flows if wished
180  if (oc.getBool("guess-empty-flows")) {
181  optNet->buildDetectorDependencies(detectors);
182  detectors.guessEmptyFlows(flows);
183  }
184 
185  const SUMOTime begin = string2time(oc.getString("begin"));
186  const SUMOTime end = string2time(oc.getString("end"));
187  const SUMOTime step = string2time(oc.getString("time-step"));
188 
189  // save emitters if wished
190  if (oc.isSet("emitters-output") || oc.isSet("emitters-poi-output")) {
191  optNet->buildEdgeFlowMap(flows, detectors, begin, end, step); // !!!
192  if (oc.getBool("revalidate-flows")) {
193  PROGRESS_BEGIN_MESSAGE("Rechecking loaded flows");
194  optNet->revalidateFlows(detectors, flows, begin, end, step);
196  }
197  if (oc.isSet("emitters-output")) {
198  PROGRESS_BEGIN_MESSAGE("Writing emitters");
199  detectors.writeEmitters(oc.getString("emitters-output"), flows,
200  begin, end, step,
201  *optNet,
202  oc.getBool("calibrator-output"),
203  oc.getBool("include-unused-routes"),
204  oc.getFloat("scale"),
205 // oc.getInt("max-search-depth"),
206  oc.getBool("emissions-only"));
208  }
209  if (oc.isSet("emitters-poi-output")) {
210  PROGRESS_BEGIN_MESSAGE("Writing emitter pois");
211  detectors.writeEmitterPOIs(oc.getString("emitters-poi-output"), flows);
213  }
214  }
215  // save end speed trigger if wished
216  if (oc.isSet("variable-speed-sign-output")) {
217  PROGRESS_BEGIN_MESSAGE("Writing speed triggers");
218  detectors.writeSpeedTrigger(optNet, oc.getString("variable-speed-sign-output"), flows,
219  begin, end, step);
221  }
222  // save checking detectors if wished
223  if (oc.isSet("validation-output")) {
224  PROGRESS_BEGIN_MESSAGE("Writing validation detectors");
225  detectors.writeValidationDetectors(oc.getString("validation-output"),
226  oc.getBool("validation-output.add-sources"), true, true); // !!!
228  }
229  // build global rerouter on end if wished
230  if (oc.isSet("end-reroute-output")) {
231  PROGRESS_BEGIN_MESSAGE("Writing highway end rerouter");
232  detectors.writeEndRerouterDetectors(oc.getString("end-reroute-output")); // !!!
234  }
235  /*
236  // save the insertion definitions
237  if(oc.isSet("flow-definitions")) {
238  buildVehicleEmissions(oc.getString("flow-definitions"));
239  }
240  */
241  //
242 }
243 
244 
245 /* -------------------------------------------------------------------------
246  * main
247  * ----------------------------------------------------------------------- */
248 int
249 main(int argc, char** argv) {
251  // give some application descriptions
252  oc.setApplicationDescription("Builds vehicle routes for SUMO using detector values.");
253  oc.setApplicationName("dfrouter", "Eclipse SUMO dfrouter Version " VERSION_STRING);
254  int ret = 0;
255  RODFNet* net = nullptr;
256  RODFDetectorCon* detectors = nullptr;
257  RODFDetectorFlows* flows = nullptr;
258  try {
259  // initialise the application system (messaging, xml, options)
260  XMLSubSys::init();
262  OptionsIO::setArgs(argc, argv);
264  if (oc.processMetaOptions(argc < 2)) {
266  return 0;
267  }
269  XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), "never");
271  if (!RODFFrame::checkOptions()) {
272  throw ProcessError();
273  }
275  // load data
276  ROLoader loader(oc, false, !oc.getBool("no-step-log"));
277  net = new RODFNet(oc.getBool("highway-mode"));
278  RODFEdgeBuilder builder;
279  loader.loadNet(*net, builder);
280  net->buildApproachList();
281  // load detectors
282  detectors = new RODFDetectorCon();
283  readDetectors(*detectors, oc, net);
284  // load detector values
285  flows = new RODFDetectorFlows(string2time(oc.getString("begin")), string2time(oc.getString("end")),
286  string2time(oc.getString("time-step")));
287  readDetectorFlows(*flows, oc, *detectors);
288  // build routes
289  startComputation(net, *flows, *detectors, oc);
290  } catch (const ProcessError& e) {
291  if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
292  WRITE_ERROR(e.what());
293  }
294  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
295  ret = 1;
296 #ifndef _DEBUG
297  } catch (const std::exception& e) {
298  if (std::string(e.what()) != std::string("")) {
299  WRITE_ERROR(e.what());
300  }
301  MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
302  ret = 1;
303  } catch (...) {
304  MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
305  ret = 1;
306 #endif
307  }
308  delete net;
309  delete flows;
310  delete detectors;
312  if (ret == 0) {
313  std::cout << "Success." << std::endl;
314  }
315  return ret;
316 }
317 
318 
319 /****************************************************************************/
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:280
#define PROGRESS_FAILED_MESSAGE()
Definition: MsgHandler.h:283
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:279
@ SOURCE_DETECTOR
A source detector.
Definition: RODFDetector.h:67
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
long long int SUMOTime
Definition: SUMOTime.h:31
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:48
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
Definition: MsgHandler.cpp:117
static void initOutputOptions()
init output options
Definition: MsgHandler.cpp:217
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
void setApplicationName(const std::string &appName, const std::string &fullName)
Sets the application name.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void setApplicationDescription(const std::string &appDesc)
Sets the application description.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition: OptionsIO.cpp:58
static void getOptions(const bool commandLineOnly=false)
Parses the command line arguments and loads the configuration.
Definition: OptionsIO.cpp:79
A loader for detector flows.
void read(const std::string &file)
Reads the given file assuming it contains detector values.
A container for RODFDetectors.
Definition: RODFDetector.h:218
bool detectorsHaveRoutes() const
void save(const std::string &file) const
void writeEmitterPOIs(const std::string &file, const RODFDetectorFlows &flows)
void writeValidationDetectors(const std::string &file, bool includeSources, bool singleFile, bool friendly)
void guessEmptyFlows(RODFDetectorFlows &flows)
bool detectorsHaveCompleteTypes() const
void saveRoutes(const std::string &file) const
void writeSpeedTrigger(const RODFNet *const net, const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset)
void writeEmitters(const std::string &file, const RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset, const RODFNet &net, bool writeCalibrators, bool includeUnusedRoutes, double scale, bool insertionsOnly)
void saveAsPOIs(const std::string &file) const
const std::vector< RODFDetector * > & getDetectors() const
void writeEndRerouterDetectors(const std::string &file)
A container for flows.
void printAbsolute() const
SAX2-Handler for loading DFROUTER-detector definitions.
Interface for building instances of dfrouter-edges.
static bool checkOptions()
Checks set options from the OptionsCont-singleton for being valid for usage within dfrouter.
Definition: RODFFrame.cpp:250
static void fillOptions()
Inserts options used by dfrouter into the OptionsCont-singleton.
Definition: RODFFrame.cpp:45
A DFROUTER-network.
Definition: RODFNet.h:42
void buildEdgeFlowMap(const RODFDetectorFlows &flows, const RODFDetectorCon &detectors, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset)
Definition: RODFNet.cpp:922
void computeTypes(RODFDetectorCon &dets, bool sourcesStrict) const
Definition: RODFNet.cpp:109
void revalidateFlows(const RODFDetectorCon &detectors, RODFDetectorFlows &flows, SUMOTime startTime, SUMOTime endTime, SUMOTime stepOffset)
Definition: RODFNet.cpp:565
void buildRoutes(RODFDetectorCon &det, bool keepUnfoundEnds, bool includeInBetween, bool keepShortestOnly, int maxFollowingLength) const
Definition: RODFNet.cpp:341
void buildDetectorDependencies(RODFDetectorCon &detectors)
Definition: RODFNet.cpp:1020
void removeEmptyDetectors(RODFDetectorCon &detectors, RODFDetectorFlows &flows)
Definition: RODFNet.cpp:579
void buildApproachList()
Definition: RODFNet.cpp:63
void reportEmptyDetectors(RODFDetectorCon &detectors, RODFDetectorFlows &flows)
Definition: RODFNet.cpp:602
The data loader.
Definition: ROLoader.h:53
virtual void loadNet(RONet &toFill, ROAbstractEdgeBuilder &eb)
Loads the network.
Definition: ROLoader.cpp:112
static void initRandGlobal(std::mt19937 *which=nullptr)
Reads the given random number options and initialises the random number generator in accordance.
Definition: RandHelper.cpp:76
static void close()
Closes all of an applications subsystems.
static bool checkOptions()
checks shared options and sets StdDefs
static void setValidation(const std::string &validationScheme, const std::string &netValidationScheme, const std::string &routeValidationScheme)
Enables or disables validation.
Definition: XMLSubSys.cpp:65
static void init()
Initialises the xml-subsystem.
Definition: XMLSubSys.cpp:54
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
int main(int argc, char **argv)
void readDetectors(RODFDetectorCon &detectors, OptionsCont &oc, RODFNet *optNet)
void startComputation(RODFNet *optNet, RODFDetectorFlows &flows, RODFDetectorCon &detectors, OptionsCont &oc)
void readDetectorFlows(RODFDetectorFlows &flows, OptionsCont &oc, RODFDetectorCon &dc)