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 dfrouter_main.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Eric Nicolay
17 : /// @author Jakob Erdmann
18 : /// @author Sascha Krieg
19 : /// @author Michael Behrisch
20 : /// @author Laura Bieker
21 : /// @date Thu, 16.03.2006
22 : ///
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>
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/FileHelpers.h>
43 : #include <utils/options/Option.h>
44 : #include <utils/options/OptionsCont.h>
45 : #include <utils/options/OptionsIO.h>
46 : #include <utils/iodevices/OutputDevice.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 244 : readDetectors(RODFDetectorCon& detectors, OptionsCont& oc, RODFNet* optNet) {
69 488 : if (!oc.isSet("detector-files")) {
70 2 : throw ProcessError(TL("No detector file given (use --detector-files <FILE>)."));
71 : }
72 : // read definitions stored in XML-format
73 486 : std::vector<std::string> files = oc.getStringVector("detector-files");
74 467 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
75 488 : if (!FileHelpers::isReadable(*fileIt)) {
76 22 : throw ProcessError(TLF("Could not open detector file '%'", *fileIt));
77 : }
78 478 : PROGRESS_BEGIN_MESSAGE("Loading detector definitions from '" + *fileIt + "'");
79 239 : RODFDetectorHandler handler(optNet, oc.getBool("ignore-invalid-detectors"), detectors, *fileIt);
80 239 : if (XMLSubSys::runParser(handler, *fileIt)) {
81 224 : PROGRESS_DONE_MESSAGE();
82 : } else {
83 15 : PROGRESS_FAILED_MESSAGE();
84 15 : throw ProcessError();
85 : }
86 239 : }
87 223 : if (detectors.getDetectors().empty()) {
88 2 : throw ProcessError(TL("No detectors found."));
89 : }
90 243 : }
91 :
92 :
93 : void
94 222 : readDetectorFlows(RODFDetectorFlows& flows, OptionsCont& oc, RODFDetectorCon& dc) {
95 444 : if (!oc.isSet("measure-files")) {
96 : // ok, not given, return an empty container
97 108 : return;
98 : }
99 : // check whether the file exists
100 228 : std::vector<std::string> files = oc.getStringVector("measure-files");
101 220 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
102 230 : if (!FileHelpers::isReadable(*fileIt)) {
103 22 : throw ProcessError(TLF("The measure-file '%' can not be opened.", *fileIt));
104 : }
105 : // parse
106 220 : PROGRESS_BEGIN_MESSAGE("Loading flows from '" + *fileIt + "'");
107 330 : RODFDetFlowLoader dfl(dc, flows, string2time(oc.getString("begin")), string2time(oc.getString("end")),
108 440 : string2time(oc.getString("time-offset")), string2time(oc.getString("time-factor")));
109 110 : dfl.read(*fileIt);
110 106 : PROGRESS_DONE_MESSAGE();
111 110 : }
112 114 : }
113 :
114 :
115 : void
116 213 : startComputation(RODFNet* optNet, RODFDetectorFlows& flows, RODFDetectorCon& detectors, OptionsCont& oc) {
117 426 : if (oc.getBool("print-absolute-flows")) {
118 0 : flows.printAbsolute();
119 : }
120 :
121 : // if a network was loaded... (mode1)
122 213 : if (optNet != nullptr) {
123 426 : if (oc.getBool("remove-empty-detectors")) {
124 14 : PROGRESS_BEGIN_MESSAGE(TL("Removing empty detectors"));
125 7 : optNet->removeEmptyDetectors(detectors, flows);
126 7 : PROGRESS_DONE_MESSAGE();
127 412 : } else if (oc.getBool("report-empty-detectors")) {
128 14 : PROGRESS_BEGIN_MESSAGE(TL("Scanning for empty detectors"));
129 7 : optNet->reportEmptyDetectors(detectors, flows);
130 7 : PROGRESS_DONE_MESSAGE();
131 : }
132 : // compute the detector types (optionally)
133 218 : if (!detectors.detectorsHaveCompleteTypes() || oc.getBool("revalidate-detectors")) {
134 416 : optNet->computeTypes(detectors, oc.getBool("strict-sources"));
135 : }
136 213 : std::vector<RODFDetector*>::const_iterator i = detectors.getDetectors().begin();
137 222 : for (; i != detectors.getDetectors().end(); ++i) {
138 221 : if ((*i)->getType() == SOURCE_DETECTOR) {
139 : break;
140 : }
141 : }
142 214 : if (i == detectors.getDetectors().end() && !oc.getBool("routes-for-all")) {
143 2 : throw ProcessError(TL("No source detectors found."));
144 : }
145 : // compute routes between the detectors (optionally)
146 212 : if (!detectors.detectorsHaveRoutes() || oc.getBool("revalidate-routes") || oc.getBool("guess-empty-flows")) {
147 424 : PROGRESS_BEGIN_MESSAGE(TL("Computing routes"));
148 424 : optNet->buildRoutes(detectors,
149 424 : oc.getBool("keep-unfinished-routes"), oc.getBool("routes-for-all"),
150 424 : !oc.getBool("keep-longer-routes"), oc.getInt("max-search-depth"));
151 212 : PROGRESS_DONE_MESSAGE();
152 : }
153 : }
154 :
155 : // check
156 : // whether the detectors are valid
157 212 : if (!detectors.detectorsHaveCompleteTypes()) {
158 0 : throw ProcessError(TL("The detector types are not defined; use in combination with a network"));
159 : }
160 : // whether the detectors have routes
161 212 : if (!detectors.detectorsHaveRoutes()) {
162 0 : throw ProcessError(TL("The emitters have no routes; use in combination with a network"));
163 : }
164 :
165 : // save the detectors if wished
166 424 : if (oc.isSet("detector-output")) {
167 36 : detectors.save(oc.getString("detector-output"));
168 : }
169 : // save their positions as POIs if wished
170 422 : if (oc.isSet("detectors-poi-output")) {
171 11 : detectors.saveAsPOIs(oc.getString("detectors-poi-output"));
172 : }
173 :
174 : // save the routes file if it was changed or it's wished
175 521 : if (detectors.detectorsHaveRoutes() && oc.isSet("routes-output")) {
176 218 : detectors.saveRoutes(oc.getString("routes-output"));
177 : }
178 :
179 : // guess flows if wished
180 418 : if (oc.getBool("guess-empty-flows")) {
181 0 : optNet->buildDetectorDependencies(detectors);
182 0 : detectors.guessEmptyFlows(flows);
183 : }
184 :
185 418 : const SUMOTime begin = string2time(oc.getString("begin"));
186 418 : const SUMOTime end = string2time(oc.getString("end"));
187 418 : const SUMOTime step = string2time(oc.getString("time-step"));
188 :
189 : // save emitters if wished
190 314 : if (oc.isSet("emitters-output") || oc.isSet("emitters-poi-output")) {
191 104 : optNet->buildEdgeFlowMap(flows, detectors, begin, end, step); // !!!
192 208 : if (oc.getBool("revalidate-flows")) {
193 0 : PROGRESS_BEGIN_MESSAGE(TL("Rechecking loaded flows"));
194 0 : optNet->revalidateFlows(detectors, flows, begin, end, step);
195 0 : PROGRESS_DONE_MESSAGE();
196 : }
197 208 : if (oc.isSet("emitters-output")) {
198 208 : PROGRESS_BEGIN_MESSAGE(TL("Writing emitters"));
199 418 : detectors.writeEmitters(oc.getString("emitters-output"), flows,
200 : begin, end, step,
201 : *optNet,
202 208 : oc.getBool("calibrator-output"),
203 208 : oc.getBool("include-unused-routes"),
204 : oc.getFloat("scale"),
205 : // oc.getInt("max-search-depth"),
206 104 : oc.getBool("emissions-only"));
207 102 : PROGRESS_DONE_MESSAGE();
208 : }
209 204 : if (oc.isSet("emitters-poi-output")) {
210 0 : PROGRESS_BEGIN_MESSAGE(TL("Writing emitter pois"));
211 0 : detectors.writeEmitterPOIs(oc.getString("emitters-poi-output"), flows);
212 0 : PROGRESS_DONE_MESSAGE();
213 : }
214 : }
215 : // save end speed trigger if wished
216 414 : if (oc.isSet("variable-speed-sign-output")) {
217 0 : PROGRESS_BEGIN_MESSAGE(TL("Writing speed triggers"));
218 0 : detectors.writeSpeedTrigger(optNet, oc.getString("variable-speed-sign-output"), flows,
219 : begin, end, step);
220 0 : PROGRESS_DONE_MESSAGE();
221 : }
222 : // save checking detectors if wished
223 414 : if (oc.isSet("validation-output")) {
224 0 : PROGRESS_BEGIN_MESSAGE(TL("Writing validation detectors"));
225 0 : detectors.writeValidationDetectors(oc.getString("validation-output"),
226 0 : oc.getBool("validation-output.add-sources"), true, true); // !!!
227 0 : PROGRESS_DONE_MESSAGE();
228 : }
229 : // build global rerouter on end if wished
230 414 : if (oc.isSet("end-reroute-output")) {
231 0 : PROGRESS_BEGIN_MESSAGE(TL("Writing highway end rerouter"));
232 0 : detectors.writeEndRerouterDetectors(oc.getString("end-reroute-output")); // !!!
233 0 : PROGRESS_DONE_MESSAGE();
234 : }
235 : /*
236 : // save the insertion definitions
237 : if(oc.isSet("flow-definitions")) {
238 : buildVehicleEmissions(oc.getString("flow-definitions"));
239 : }
240 : */
241 : //
242 207 : }
243 :
244 :
245 : /* -------------------------------------------------------------------------
246 : * main
247 : * ----------------------------------------------------------------------- */
248 : int
249 730 : main(int argc, char** argv) {
250 730 : OptionsCont& oc = OptionsCont::getOptions();
251 730 : oc.setApplicationDescription(TL("Builds vehicle routes for SUMO using detector values."));
252 1460 : oc.setApplicationName("dfrouter", "Eclipse SUMO dfrouter Version " VERSION_STRING);
253 : int ret = 0;
254 : RODFNet* net = nullptr;
255 : RODFDetectorCon* detectors = nullptr;
256 : RODFDetectorFlows* flows = nullptr;
257 : try {
258 : // initialise the application system (messaging, xml, options)
259 730 : XMLSubSys::init();
260 730 : RODFFrame::fillOptions();
261 730 : OptionsIO::setArgs(argc, argv);
262 730 : OptionsIO::getOptions();
263 720 : if (oc.processMetaOptions(argc < 2)) {
264 6 : SystemFrame::close();
265 6 : return 0;
266 : }
267 714 : SystemFrame::checkOptions(oc);
268 2142 : XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), "never");
269 714 : MsgHandler::initOutputOptions();
270 714 : if (!RODFFrame::checkOptions()) {
271 0 : throw ProcessError();
272 : }
273 714 : RandHelper::initRandGlobal();
274 : // load data
275 714 : ROLoader loader(oc, false, !oc.getBool("no-step-log"));
276 714 : net = new RODFNet(oc.getBool("highway-mode"));
277 714 : RODFEdgeBuilder builder;
278 714 : loader.loadNet(*net, builder);
279 244 : net->buildApproachList();
280 : // load detectors
281 244 : detectors = new RODFDetectorCon();
282 244 : readDetectors(*detectors, oc, net);
283 : // load detector values
284 444 : flows = new RODFDetectorFlows(string2time(oc.getString("begin")), string2time(oc.getString("end")),
285 444 : string2time(oc.getString("time-step")));
286 222 : readDetectorFlows(*flows, oc, *detectors);
287 : // build routes
288 213 : startComputation(net, *flows, *detectors, oc);
289 1738 : } catch (const ProcessError& e) {
290 619 : if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
291 68 : WRITE_ERROR(e.what());
292 : }
293 517 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
294 : ret = 1;
295 : #ifndef _DEBUG
296 517 : } catch (const std::exception& e) {
297 0 : if (std::string(e.what()) != std::string("")) {
298 0 : WRITE_ERROR(e.what());
299 : }
300 0 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
301 : ret = 1;
302 0 : } catch (...) {
303 0 : MsgHandler::getErrorInstance()->inform("Quitting (on unknown error).", false);
304 : ret = 1;
305 : #endif
306 0 : }
307 724 : delete net;
308 724 : delete flows;
309 724 : delete detectors;
310 724 : SystemFrame::close();
311 724 : if (ret == 0) {
312 : std::cout << "Success." << std::endl;
313 : }
314 : return ret;
315 : }
316 :
317 :
318 : /****************************************************************************/
|