Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 NLBuilder.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Mon, 9 Jul 2001
19 : ///
20 : // The main interface for loading a microsim
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <iostream>
25 : #include <vector>
26 : #include <string>
27 : #include <map>
28 :
29 : #include <utils/common/MsgHandler.h>
30 : #include <utils/common/StringTokenizer.h>
31 : #include <utils/common/SystemFrame.h>
32 : #include <utils/options/Option.h>
33 : #include <utils/options/OptionsCont.h>
34 : #include <utils/options/OptionsIO.h>
35 : #include <utils/common/StringUtils.h>
36 : #include <utils/common/FileHelpers.h>
37 : #include <utils/common/SysUtils.h>
38 : #include <utils/common/ToString.h>
39 : #include <utils/vehicle/SUMORouteLoaderControl.h>
40 : #include <utils/vehicle/SUMORouteLoader.h>
41 : #include <utils/xml/XMLSubSys.h>
42 : #ifdef HAVE_FOX
43 : #include <utils/foxtools/MsgHandlerSynchronized.h>
44 : #endif
45 : #include <libsumo/Helper.h>
46 : #include <mesosim/MEVehicleControl.h>
47 : #include <mesosim/METypeHandler.h>
48 : #include <microsim/MSVehicleControl.h>
49 : #include <microsim/MSVehicleTransfer.h>
50 : #include <microsim/MSNet.h>
51 : #include <microsim/devices/MSDevice.h>
52 : #include <microsim/devices/MSDevice_ToC.h>
53 : #include <microsim/devices/MSDevice_BTreceiver.h>
54 : #include <microsim/devices/MSDevice_FCDReplay.h>
55 : #include <microsim/devices/MSRoutingEngine.h>
56 : #include <microsim/MSEdgeControl.h>
57 : #include <microsim/MSGlobals.h>
58 : #include <microsim/output/MSDetectorControl.h>
59 : #include <microsim/MSFrame.h>
60 : #include <microsim/MSEdgeWeightsStorage.h>
61 : #include <microsim/MSStateHandler.h>
62 : #include <microsim/MSDriverState.h>
63 : #include <microsim/trigger/MSTriggeredRerouter.h>
64 : #include <traci-server/TraCIServer.h>
65 :
66 : #include "NLHandler.h"
67 : #include "NLNetShapeHandler.h"
68 : #include "NLEdgeControlBuilder.h"
69 : #include "NLJunctionControlBuilder.h"
70 : #include "NLDetectorBuilder.h"
71 : #include "NLTriggerBuilder.h"
72 : #include "NLBuilder.h"
73 :
74 :
75 : // ===========================================================================
76 : // method definitions
77 : // ===========================================================================
78 : // ---------------------------------------------------------------------------
79 : // NLBuilder::EdgeFloatTimeLineRetriever_EdgeWeight - methods
80 : // ---------------------------------------------------------------------------
81 : void
82 0 : NLBuilder::EdgeFloatTimeLineRetriever_EdgeEffort::addEdgeWeight(const std::string& id,
83 : double value, double begTime, double endTime) const {
84 0 : MSEdge* edge = MSEdge::dictionary(id);
85 0 : if (edge != nullptr) {
86 0 : myNet.getWeightsStorage().addEffort(edge, begTime, endTime, value);
87 : } else {
88 0 : WRITE_ERRORF(TL("Trying to set the effort for the unknown edge '%'."), id);
89 : }
90 0 : }
91 :
92 :
93 : // ---------------------------------------------------------------------------
94 : // NLBuilder::EdgeFloatTimeLineRetriever_EdgeTravelTime - methods
95 : // ---------------------------------------------------------------------------
96 : void
97 18 : NLBuilder::EdgeFloatTimeLineRetriever_EdgeTravelTime::addEdgeWeight(const std::string& id,
98 : double value, double begTime, double endTime) const {
99 18 : MSEdge* edge = MSEdge::dictionary(id);
100 18 : if (edge != nullptr) {
101 18 : myNet.getWeightsStorage().addTravelTime(edge, begTime, endTime, value);
102 : } else {
103 0 : WRITE_ERRORF(TL("Trying to set the travel time for the unknown edge '%'."), id);
104 : }
105 18 : }
106 :
107 :
108 : // ---------------------------------------------------------------------------
109 : // NLBuilder - methods
110 : // ---------------------------------------------------------------------------
111 42489 : NLBuilder::NLBuilder(OptionsCont& oc,
112 : MSNet& net,
113 : NLEdgeControlBuilder& eb,
114 : NLJunctionControlBuilder& jb,
115 : NLDetectorBuilder& db,
116 42489 : NLHandler& xmlHandler)
117 42489 : : myOptions(oc), myEdgeBuilder(eb), myJunctionBuilder(jb),
118 42489 : myDetectorBuilder(db),
119 42489 : myNet(net), myXMLHandler(xmlHandler) {}
120 :
121 :
122 42489 : NLBuilder::~NLBuilder() {}
123 :
124 :
125 : bool
126 42489 : NLBuilder::build() {
127 : // try to build the net
128 84978 : if (!load("net-file", true)) {
129 : return false;
130 : }
131 42193 : if (myXMLHandler.networkVersion() == MMVersion(0, 0)) {
132 0 : throw ProcessError(TL("Invalid network, no network version declared."));
133 : }
134 : // check whether the loaded net agrees with the simulation options
135 84386 : if ((myOptions.getBool("no-internal-links")) && myXMLHandler.haveSeenInternalEdge() && myXMLHandler.haveSeenDefaultLength()) {
136 174 : WRITE_WARNING(TL("Network contains internal links which are ignored. Vehicles will 'jump' across junctions and thus underestimate route lengths and travel times."));
137 : }
138 57098 : if (!myXMLHandler.haveSeenInternalEdge() && myOptions.getBool("mesosim")) {
139 : // @todo: setting this option has some side effect in microsim that manifest even in networks without internal lanes this should be checked
140 3312 : MSGlobals::gUsingInternalLanes = false;
141 : }
142 42193 : buildNet();
143 84032 : if (myOptions.isSet("alternative-net-file")) {
144 0 : for (std::string fname : myOptions.getStringVector("alternative-net-file")) {
145 0 : const long before = PROGRESS_BEGIN_TIME_MESSAGE("Loading alternative net from '" + fname + "'");
146 0 : NLNetShapeHandler nsh(fname, myNet);
147 0 : if (!XMLSubSys::runParser(nsh, fname, true)) {
148 0 : WRITE_MESSAGE("Loading of alternative net failed.");
149 : return false;
150 : }
151 0 : nsh.sortInternalShapes();
152 0 : PROGRESS_TIME_MESSAGE(before);
153 0 : }
154 : }
155 : // @note on loading order constraints:
156 : // - additional-files before route-files and state-files due to referencing
157 : // - additional-files before weight-files since the latter might contain intermodal edge data and the intermodal net depends on the stops and public transport from the additionals
158 :
159 : bool stateBeginMismatch = false;
160 42016 : const SUMOTime stateOffset = string2time(myOptions.getString("load-state.offset"));
161 84032 : if (myOptions.isSet("load-state")) {
162 : // first, load only the time
163 308 : const SUMOTime stateTime = MSStateHandler::MSStateTimeHandler::getTime(myOptions.getString("load-state"));
164 301 : bool defaultBegin = myOptions.isDefault("begin");
165 602 : if (stateTime != string2time(myOptions.getString("begin"))) {
166 506 : if (myOptions.isDefault("load-state.offset")) {
167 239 : if (!defaultBegin) {
168 27 : WRITE_WARNINGF(TL("State was written at a different time=% than the begin time % (set option load-state.offset to force a different begin)!"),
169 : time2string(stateTime), myOptions.getString("begin"));
170 : }
171 478 : myOptions.resetWritable("begin");
172 : defaultBegin = true;
173 : } else {
174 : stateBeginMismatch = true;
175 : }
176 : }
177 62 : if (defaultBegin) {
178 488 : myOptions.set("begin", time2string(stateTime));
179 : // if vehicles are deliberately removed from the state, we must allow them to be reloaded from a route file at state time
180 244 : SUMOTime allowReloadOffset = myOptions.isDefault("load-state.remove-vehicles") ? 0 : 1;
181 244 : myNet.setLoaderTime(stateTime - allowReloadOffset);
182 244 : if (TraCIServer::getInstance() != nullptr) {
183 21 : TraCIServer::getInstance()->stateLoaded(stateTime);
184 : }
185 : }
186 602 : myNet.setCurrentTimeStep(string2time(myOptions.getString("begin")));
187 : }
188 :
189 84018 : if (myOptions.getBool("junction-taz")) {
190 : // create a TAZ for every junction
191 1039 : const MSJunctionControl& junctions = myNet.getJunctionControl();
192 21459 : for (auto it = junctions.begin(); it != junctions.end(); it++) {
193 20420 : const std::string sinkID = it->first + "-sink";
194 20420 : const std::string sourceID = it->first + "-source";
195 20420 : if (MSEdge::dictionary(sinkID) == nullptr && MSEdge::dictionary(sourceID) == nullptr) {
196 : // sink must be built and added before source
197 40840 : MSEdge* sink = myEdgeBuilder.buildEdge(sinkID, SumoXMLEdgeFunc::CONNECTOR, "", "", "", -1, 0);
198 40840 : MSEdge* source = myEdgeBuilder.buildEdge(sourceID, SumoXMLEdgeFunc::CONNECTOR, "", "", "", -1, 0);
199 : sink->setOtherTazConnector(source);
200 : source->setOtherTazConnector(sink);
201 20420 : MSEdge::dictionary(sinkID, sink);
202 20420 : MSEdge::dictionary(sourceID, source);
203 20420 : sink->initialize(new std::vector<MSLane*>());
204 20420 : source->initialize(new std::vector<MSLane*>());
205 20420 : const MSJunction* junction = it->second;
206 100801 : for (const MSEdge* edge : junction->getIncoming()) {
207 80381 : if (!edge->isInternal()) {
208 33496 : const_cast<MSEdge*>(edge)->addSuccessor(sink);
209 : }
210 : }
211 100801 : for (const MSEdge* edge : junction->getOutgoing()) {
212 80381 : if (!edge->isInternal()) {
213 33496 : source->addSuccessor(const_cast<MSEdge*>(edge));
214 : }
215 : }
216 : } else {
217 0 : WRITE_WARNINGF(TL("A TAZ with id '%' already exists. Not building junction TAZ."), it->first)
218 : }
219 : }
220 : }
221 : // load meso edge types
222 : bool haveSeenMesoEdgeType = false;
223 42009 : if (MSGlobals::gUseMesoSim) {
224 13540 : if (myOptions.isSet("additional-files")) {
225 7584 : haveSeenMesoEdgeType = loadMesoEdgeTypes("additional-files");
226 : }
227 : // meso segment building must be delayed until meso edge types have been read from additional files
228 6770 : myNet.getEdgeControl().buildMesoSegments();
229 : }
230 : // load additional net elements (sources, detectors, ...)
231 84018 : if (myOptions.isSet("additional-files")) {
232 53964 : if (!load("additional-files")) {
233 776 : return false;
234 : }
235 : // load shapes with separate handler
236 26206 : NLShapeHandler sh("", myNet.getShapeContainer());
237 52412 : if (!ShapeHandler::loadFiles(myOptions.getStringVector("additional-files"), sh)) {
238 : return false;
239 : }
240 26206 : if (myXMLHandler.haveSeenAdditionalSpeedRestrictions()) {
241 65 : myNet.getEdgeControl().setAdditionalRestrictions();
242 : }
243 26206 : MSTriggeredRerouter::checkParkingRerouteConsistency();
244 : }
245 41233 : if (MSGlobals::gUseMesoSim) {
246 6576 : if (haveSeenMesoEdgeType || myXMLHandler.haveSeenTLSParams()) {
247 111 : for (MSTrafficLightLogic* tll : myNet.getTLSControl().getAllLogics()) {
248 58 : tll->initMesoTLSPenalties();
249 53 : }
250 : }
251 : }
252 : // init after preferences have been loaded from additional-files
253 41233 : MSRoutingEngine::initWeightConstants(myOptions);
254 : // init tls after all detectors have been loaded
255 41233 : myJunctionBuilder.postLoadInitialization();
256 : // declare meandata set by options
257 82414 : buildDefaultMeanData("edgedata-output", "DEFAULT_EDGEDATA", false);
258 82414 : buildDefaultMeanData("lanedata-output", "DEFAULT_LANEDATA", true);
259 :
260 41207 : if (stateBeginMismatch && myNet.getVehicleControl().getLoadedVehicleNo() > 0) {
261 2 : throw ProcessError(TL("Loading vehicles ahead of a state file is not supported. Correct --begin option or load vehicles with option --route-files"));
262 : }
263 :
264 : // load weights if wished
265 82412 : if (myOptions.isSet("weight-files")) {
266 22 : if (!myOptions.isUsableFileList("weight-files")) {
267 0 : return false;
268 : }
269 : // build and prepare the weights handler
270 : std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
271 : // travel time, first (always used)
272 11 : EdgeFloatTimeLineRetriever_EdgeTravelTime ttRetriever(myNet);
273 11 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition("traveltime", true, ttRetriever));
274 : // the measure to use, then
275 11 : EdgeFloatTimeLineRetriever_EdgeEffort eRetriever(myNet);
276 11 : std::string measure = myOptions.getString("weight-attribute");
277 22 : if (!myOptions.isDefault("weight-attribute")) {
278 0 : if (measure == "CO" || measure == "CO2" || measure == "HC" || measure == "PMx" || measure == "NOx" || measure == "fuel" || measure == "electricity") {
279 : measure += "_perVeh";
280 : }
281 0 : retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(measure, true, eRetriever));
282 : }
283 : // set up handler
284 11 : SAXWeightsHandler handler(retrieverDefs, "");
285 : // start parsing; for each file in the list
286 22 : std::vector<std::string> files = myOptions.getStringVector("weight-files");
287 22 : for (std::vector<std::string>::iterator i = files.begin(); i != files.end(); ++i) {
288 : // report about loading when wished
289 33 : WRITE_MESSAGEF(TL("Loading weights from '%'..."), *i);
290 : // parse the file
291 11 : if (!XMLSubSys::runParser(handler, *i)) {
292 : return false;
293 : }
294 : }
295 22 : }
296 : // load the previous state if wished
297 82412 : if (myOptions.isSet("load-state")) {
298 300 : const std::string& f = myOptions.getString("load-state");
299 900 : long before = PROGRESS_BEGIN_TIME_MESSAGE(TLF("Loading state from '%'", f));
300 300 : MSStateHandler h(f, stateOffset);
301 300 : XMLSubSys::runParser(h, f);
302 300 : if (MsgHandler::getErrorInstance()->wasInformed()) {
303 : return false;
304 : }
305 294 : PROGRESS_TIME_MESSAGE(before);
306 300 : }
307 : // routes from FCD files
308 41200 : MSDevice_FCDReplay::init();
309 : // load routes
310 82400 : if (myOptions.isSet("route-files")) {
311 67118 : if (string2time(myOptions.getString("route-steps")) <= 0) {
312 : // incremental loading is disabled. Load route files fully
313 0 : if (!load("route-files")) {
314 : return false;
315 : }
316 : } else {
317 : // message must come after additional-files have been loaded (but buildRouteLoaderControl was called earlier)
318 101638 : for (std::string file : myOptions.getStringVector("route-files")) {
319 103560 : WRITE_MESSAGE(TLF("Loading route-files incrementally from '%'", file));
320 : }
321 : }
322 : }
323 : // optionally switch off traffic lights
324 82400 : if (myOptions.getBool("tls.all-off")) {
325 120 : myNet.getTLSControl().switchOffAll();
326 : }
327 41200 : WRITE_MESSAGE(TL("Loading done."));
328 41200 : return true;
329 : }
330 :
331 :
332 : MSNet*
333 36495 : NLBuilder::init(const bool isLibsumo) {
334 36495 : OptionsCont& oc = OptionsCont::getOptions();
335 36495 : oc.clear();
336 36495 : MSFrame::fillOptions();
337 36495 : OptionsIO::getOptions();
338 36210 : if (oc.processMetaOptions(OptionsIO::getArgC() < 2)) {
339 387 : SystemFrame::close();
340 387 : return nullptr;
341 : }
342 35823 : SystemFrame::checkOptions(oc);
343 35823 : std::string validation = oc.getString("xml-validation");
344 39353 : std::string routeValidation = oc.getString("xml-validation.routes");
345 35823 : if (isLibsumo) {
346 1210 : if (oc.isDefault("xml-validation")) {
347 : validation = "never";
348 : }
349 1210 : if (oc.isDefault("xml-validation.routes")) {
350 : routeValidation = "never";
351 : }
352 : }
353 35823 : XMLSubSys::setValidation(validation, oc.getString("xml-validation.net"), routeValidation);
354 35823 : if (!MSFrame::checkOptions()) {
355 2109 : throw ProcessError();
356 : }
357 : #ifdef HAVE_FOX
358 67412 : if (oc.getInt("threads") > 1) {
359 : // make the output aware of threading
360 : MsgHandler::setFactory(&MsgHandlerSynchronized::create);
361 : }
362 : #endif
363 33706 : MsgHandler::initOutputOptions();
364 33706 : initRandomness();
365 33706 : MSFrame::setMSGlobals(oc);
366 : MSVehicleControl* vc = nullptr;
367 33706 : if (MSGlobals::gUseMesoSim) {
368 3863 : vc = new MEVehicleControl();
369 : } else {
370 29843 : vc = new MSVehicleControl();
371 : }
372 33706 : MSNet* net = new MSNet(vc, new MSEventControl(), new MSEventControl(), new MSEventControl());
373 : // need to init TraCI-Server before loading routes to catch VehicleState::BUILT
374 37236 : TraCIServer::openSocket(std::map<int, TraCIServer::CmdExecutor>());
375 33697 : if (isLibsumo) {
376 605 : libsumo::Helper::registerStateListener();
377 : }
378 :
379 33697 : NLEdgeControlBuilder eb;
380 33697 : NLDetectorBuilder db(*net);
381 33697 : NLJunctionControlBuilder jb(*net, db);
382 33697 : NLTriggerBuilder tb;
383 33697 : NLHandler handler("", *net, db, tb, eb, jb);
384 33697 : tb.setHandler(&handler);
385 33697 : NLBuilder builder(oc, *net, eb, jb, db, handler);
386 33697 : MsgHandler::getErrorInstance()->clear();
387 33697 : MsgHandler::getWarningInstance()->clear();
388 33697 : MsgHandler::getMessageInstance()->clear();
389 33697 : if (builder.build()) {
390 : // preload the routes especially for TraCI
391 32693 : net->loadRoutes();
392 : return net;
393 : }
394 822 : delete net;
395 822 : throw ProcessError();
396 40717 : }
397 :
398 :
399 : void
400 42501 : NLBuilder::initRandomness() {
401 42501 : RandHelper::initRandGlobal();
402 42501 : RandHelper::initRandGlobal(MSRouteHandler::getParsingRNG());
403 42501 : RandHelper::initRandGlobal(MSDevice::getEquipmentRNG());
404 42501 : RandHelper::initRandGlobal(OUProcess::getRNG());
405 42501 : RandHelper::initRandGlobal(MSDevice_ToC::getResponseTimeRNG());
406 42501 : RandHelper::initRandGlobal(MSDevice_BTreceiver::getRecognitionRNG());
407 42501 : MSLane::initRNGs(OptionsCont::getOptions());
408 42501 : }
409 :
410 :
411 : void
412 42193 : NLBuilder::buildNet() {
413 : MSEdgeControl* edges = nullptr;
414 : MSJunctionControl* junctions = nullptr;
415 : SUMORouteLoaderControl* routeLoaders = nullptr;
416 : MSTLLogicControl* tlc = nullptr;
417 : std::vector<SUMOTime> stateDumpTimes;
418 : std::vector<std::string> stateDumpFiles;
419 : try {
420 42193 : MSFrame::buildStreams(); // ensure streams are ready for output during building
421 42151 : edges = myEdgeBuilder.build(myXMLHandler.networkVersion());
422 42141 : junctions = myJunctionBuilder.build();
423 42141 : junctions->postloadInitContainer();
424 1812028 : for (MSEdge* e : edges->getEdges()) {
425 1769891 : e->postLoadInitLaneChanger();
426 : }
427 42137 : routeLoaders = buildRouteLoaderControl(myOptions);
428 42016 : tlc = myJunctionBuilder.buildTLLogics();
429 84422 : for (std::string timeStr : myOptions.getStringVector("save-state.times")) {
430 390 : stateDumpTimes.push_back(string2time(timeStr));
431 : }
432 84032 : if (myOptions.isSet("save-state.files")) {
433 652 : stateDumpFiles = myOptions.getStringVector("save-state.files");
434 326 : if (stateDumpFiles.size() != stateDumpTimes.size()) {
435 0 : throw ProcessError(TL("Wrong number of state file names!"));
436 : }
437 : } else {
438 41690 : const std::string prefix = myOptions.getString("save-state.prefix");
439 83380 : const std::string suffix = myOptions.getString("save-state.suffix");
440 41708 : for (std::vector<SUMOTime>::iterator i = stateDumpTimes.begin(); i != stateDumpTimes.end(); ++i) {
441 18 : std::string timeStamp = time2string(*i);
442 : std::replace(timeStamp.begin(), timeStamp.end(), ':', '-');
443 36 : stateDumpFiles.push_back(prefix + "_" + timeStamp + suffix);
444 : }
445 : }
446 177 : } catch (ProcessError&) {
447 177 : MSEdge::clear();
448 177 : MSLane::clear();
449 177 : delete edges;
450 177 : delete junctions;
451 177 : delete routeLoaders;
452 177 : delete tlc;
453 177 : throw;
454 177 : }
455 : // if anthing goes wrong after this point, the net is responsible for cleaning up
456 42016 : myNet.closeBuilding(myOptions, edges, junctions, routeLoaders, tlc, stateDumpTimes, stateDumpFiles,
457 : myXMLHandler.haveSeenInternalEdge(),
458 : myXMLHandler.hasJunctionHigherSpeeds(),
459 42016 : myXMLHandler.networkVersion());
460 42370 : }
461 :
462 :
463 : bool
464 69471 : NLBuilder::load(const std::string& mmlWhat, const bool isNet) {
465 69471 : if (!myOptions.isUsableFileList(mmlWhat)) {
466 : return false;
467 : }
468 69458 : std::vector<std::string> files = myOptions.getStringVector(mmlWhat);
469 155266 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
470 260601 : const long before = PROGRESS_BEGIN_TIME_MESSAGE(TLF("Loading % from '%'", mmlWhat, *fileIt));
471 86867 : if (!XMLSubSys::runParser(myXMLHandler, *fileIt, isNet)) {
472 3177 : WRITE_MESSAGEF(TL("Loading of % failed."), mmlWhat);
473 : return false;
474 : }
475 85808 : PROGRESS_TIME_MESSAGE(before);
476 : }
477 : return true;
478 69458 : }
479 :
480 :
481 : bool
482 3792 : NLBuilder::loadMesoEdgeTypes(const std::string& mmlWhat) {
483 3792 : if (!myOptions.isUsableFileList(mmlWhat)) {
484 : return false;
485 : }
486 3792 : METypeHandler meTypeHandler("", myNet);
487 9297 : for (const std::string& file : myOptions.getStringVector(mmlWhat)) {
488 5505 : if (!XMLSubSys::runParser(meTypeHandler, file)) {
489 : continue;
490 : }
491 : }
492 : return meTypeHandler.haveSeenMesoEdgeType();
493 3792 : }
494 :
495 :
496 : SUMORouteLoaderControl*
497 42301 : NLBuilder::buildRouteLoaderControl(const OptionsCont& oc) {
498 : // build the loaders
499 42301 : SUMORouteLoaderControl* loaders = new SUMORouteLoaderControl(string2time(oc.getString("route-steps")));
500 : // check whether a list is existing
501 110815 : if (oc.isSet("route-files") && string2time(oc.getString("route-steps")) > 0) {
502 68514 : std::vector<std::string> files = oc.getStringVector("route-files");
503 69354 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
504 70436 : if (!FileHelpers::isReadable(*fileIt)) {
505 363 : throw ProcessError(TLF("The route file '%' is not accessible.", *fileIt));
506 : }
507 : }
508 : // open files for reading
509 69233 : for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
510 35097 : loaders->add(new SUMORouteLoader(new MSRouteHandler(*fileIt, false)));
511 : }
512 34257 : }
513 42180 : return loaders;
514 : }
515 :
516 :
517 : void
518 82414 : NLBuilder::buildDefaultMeanData(const std::string& optionName, const std::string& id, bool useLanes) {
519 82414 : if (OptionsCont::getOptions().isSet(optionName)) {
520 87 : if (useLanes && MSGlobals::gUseMesoSim && !OptionsCont::getOptions().getBool("meso-lane-queue")) {
521 4 : WRITE_WARNING(TL("LaneData requested for mesoscopic simulation but --meso-lane-queue is not active. Falling back to edgeData."));
522 : useLanes = false;
523 : }
524 : try {
525 75 : SUMOTime begin = string2time(OptionsCont::getOptions().getString("begin"));
526 150 : myDetectorBuilder.createEdgeLaneMeanData(id, -1, begin, -1, "traffic", useLanes, "true",
527 75 : false, false, 0, 100000, 0, SUMO_const_haltingSpeed, "", "", std::vector<MSEdge*>(), AggregateType::NO,
528 150 : OptionsCont::getOptions().getString(optionName));
529 0 : } catch (InvalidArgument& e) {
530 0 : WRITE_ERROR(e.what());
531 0 : } catch (IOError& e) {
532 0 : WRITE_ERROR(e.what());
533 0 : }
534 : }
535 82414 : }
536 :
537 : /****************************************************************************/
|