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