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    jtrrouter_main.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Jakob Erdmann
13 /// @author  Michael Behrisch
14 /// @date    Tue, 20 Jan 2004
15 /// @version $Id$
16 ///
17 // Main for JTRROUTER
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #ifdef HAVE_VERSION_H
27 #include <version.h>
28 #endif
29 
30 #include <iostream>
31 #include <string>
32 #include <limits.h>
33 #include <ctime>
34 #include <set>
35 #include <xercesc/sax/SAXException.hpp>
36 #include <xercesc/sax/SAXParseException.hpp>
37 #include <utils/common/StringUtils.h>
38 #include <utils/common/MsgHandler.h>
39 #include <utils/common/UtilExceptions.h>
40 #include <utils/common/SystemFrame.h>
41 #include <utils/common/ToString.h>
42 #include <utils/common/RandHelper.h>
43 #include <utils/common/StringTokenizer.h>
44 #include <utils/iodevices/OutputDevice.h>
45 #include <utils/options/Option.h>
46 #include <utils/options/OptionsCont.h>
47 #include <utils/options/OptionsIO.h>
48 #include <utils/xml/XMLSubSys.h>
49 #include <router/ROFrame.h>
50 #include <router/ROLoader.h>
51 #include <router/RONet.h>
52 #include <router/RORouteDef.h>
53 #include "ROJTREdgeBuilder.h"
54 #include "ROJTRRouter.h"
55 #include "ROJTREdge.h"
56 #include "ROJTRTurnDefLoader.h"
57 #include "ROJTRFrame.h"
58 
59 
60 // ===========================================================================
61 // functions
62 // ===========================================================================
63 /* -------------------------------------------------------------------------
64  * data processing methods
65  * ----------------------------------------------------------------------- */
66 /**
67  * loads the net
68  * The net is in this meaning made up by the net itself and the dynamic
69  * weights which may be supplied in a separate file
70  */
71 void
initNet(RONet & net,ROLoader & loader,const std::vector<double> & turnDefs)72 initNet(RONet& net, ROLoader& loader,
73         const std::vector<double>& turnDefs) {
74     // load the net
75     ROJTREdgeBuilder builder;
76     loader.loadNet(net, builder);
77     // set the turn defaults
78     for (const auto& i : net.getEdgeMap()) {
79         static_cast<ROJTREdge*>(i.second)->setTurnDefaults(turnDefs);
80     }
81 }
82 
83 std::vector<double>
getTurningDefaults(OptionsCont & oc)84 getTurningDefaults(OptionsCont& oc) {
85     std::vector<double> ret;
86     std::vector<std::string> defs = oc.getStringVector("turn-defaults");
87     if (defs.size() < 2) {
88         throw ProcessError("The defaults for turnings must be a tuple of at least two numbers divided by ','.");
89     }
90     for (std::vector<std::string>::const_iterator i = defs.begin(); i != defs.end(); ++i) {
91         try {
92             double val = StringUtils::toDouble(*i);
93             ret.push_back(val);
94         } catch (NumberFormatException&) {
95             throw ProcessError("A turn default is not numeric.");
96         }
97     }
98     return ret;
99 }
100 
101 
102 void
loadJTRDefinitions(RONet & net,OptionsCont & oc)103 loadJTRDefinitions(RONet& net, OptionsCont& oc) {
104     // load the turning definitions (and possible sink definition)
105     if (oc.isSet("turn-ratio-files")) {
106         ROJTRTurnDefLoader loader(net);
107         std::vector<std::string> ratio_files = oc.getStringVector("turn-ratio-files");
108         for (std::vector<std::string>::const_iterator i = ratio_files.begin(); i != ratio_files.end(); ++i) {
109             if (!XMLSubSys::runParser(loader, *i)) {
110                 throw ProcessError();
111             }
112         }
113     }
114     if (MsgHandler::getErrorInstance()->wasInformed() && oc.getBool("ignore-errors")) {
115         MsgHandler::getErrorInstance()->clear();
116     }
117     // parse sink edges specified at the input/within the configuration
118     if (oc.isSet("sink-edges")) {
119         std::vector<std::string> edges = oc.getStringVector("sink-edges");
120         for (std::vector<std::string>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
121             ROJTREdge* edge = static_cast<ROJTREdge*>(net.getEdge(*i));
122             if (edge == nullptr) {
123                 throw ProcessError("The edge '" + *i + "' declared as a sink is not known.");
124             }
125             edge->setSink();
126         }
127     }
128 }
129 
130 
131 /**
132  * Computes the routes saving them
133  */
134 void
computeRoutes(RONet & net,ROLoader & loader,OptionsCont & oc)135 computeRoutes(RONet& net, ROLoader& loader, OptionsCont& oc) {
136     // initialise the loader
137     loader.openRoutes(net);
138     // prepare the output
139     net.openOutput(oc);
140     // build the router
141     ROJTRRouter* router = new ROJTRRouter(oc.getBool("ignore-errors"), oc.getBool("accept-all-destinations"),
142                                           (int)(((double) net.getEdgeNumber()) * OptionsCont::getOptions().getFloat("max-edges-factor")),
143                                           oc.getBool("ignore-vclasses"), oc.getBool("allow-loops"));
144     RORouteDef::setUsingJTRR();
145     RORouterProvider provider(router, new PedestrianRouter<ROEdge, ROLane, RONode, ROVehicle>(),
146                               new ROIntermodalRouter(RONet::adaptIntermodalRouter, 0, "dijkstra"));
147     loader.processRoutes(string2time(oc.getString("begin")), string2time(oc.getString("end")),
148                          string2time(oc.getString("route-steps")), net, provider);
149     net.cleanup();
150 }
151 
152 
153 /* -------------------------------------------------------------------------
154  * main
155  * ----------------------------------------------------------------------- */
156 int
main(int argc,char ** argv)157 main(int argc, char** argv) {
158     OptionsCont& oc = OptionsCont::getOptions();
159     // give some application descriptions
160     oc.setApplicationDescription("Router for the microscopic, multi-modal traffic simulation SUMO based on junction turning ratios.");
161     oc.setApplicationName("jtrrouter", "Eclipse SUMO jtrrouter Version " VERSION_STRING);
162     int ret = 0;
163     RONet* net = nullptr;
164     try {
165         // initialise the application system (messaging, xml, options)
166         XMLSubSys::init();
167         ROJTRFrame::fillOptions();
168         OptionsIO::setArgs(argc, argv);
169         OptionsIO::getOptions();
170         if (oc.processMetaOptions(argc < 2)) {
171             SystemFrame::close();
172             return 0;
173         }
174         XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"));
175         MsgHandler::initOutputOptions();
176         if (!(ROJTRFrame::checkOptions() && SystemFrame::checkOptions())) {
177             throw ProcessError();
178         }
179         RandHelper::initRandGlobal();
180         std::vector<double> defs = getTurningDefaults(oc);
181         // load data
182         ROLoader loader(oc, true, !oc.getBool("no-step-log"));
183         net = new RONet();
184         initNet(*net, loader, defs);
185         try {
186             // parse and set the turn defaults first
187             loadJTRDefinitions(*net, oc);
188             // build routes
189             computeRoutes(*net, loader, oc);
190         } catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
191             WRITE_ERROR(toString(e.getLineNumber()));
192             ret = 1;
193         } catch (XERCES_CPP_NAMESPACE::SAXException& e) {
194             WRITE_ERROR(StringUtils::transcode(e.getMessage()));
195             ret = 1;
196         }
197         if (MsgHandler::getErrorInstance()->wasInformed()) {
198             throw ProcessError();
199         }
200     } catch (const ProcessError& e) {
201         if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
202             WRITE_ERROR(e.what());
203         }
204         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
205         ret = 1;
206 #ifndef _DEBUG
207     } catch (const std::exception& e) {
208         if (std::string(e.what()) != std::string("")) {
209             WRITE_ERROR(e.what());
210         }
211         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
212         ret = 1;
213     } catch (...) {
214         MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
215         ret = 1;
216 #endif
217     }
218     delete net;
219     SystemFrame::close();
220     if (ret == 0) {
221         std::cout << "Success." << std::endl;
222     }
223     return ret;
224 }
225 
226 
227 /****************************************************************************/
228