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 GUILoadThread.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Michael Behrisch
18 : /// @date Sept 2002
19 : ///
20 : // Class describing the thread that performs the loading of a simulation
21 : /****************************************************************************/
22 : #include <config.h>
23 :
24 : #include <iostream>
25 : #include <ctime>
26 : #include <utils/common/RandHelper.h>
27 : #include <utils/common/UtilExceptions.h>
28 : #include <utils/common/MsgHandler.h>
29 : #include <utils/common/MsgRetrievingFunction.h>
30 : #include <utils/options/OptionsCont.h>
31 : #include <utils/options/Option.h>
32 : #include <utils/options/OptionsIO.h>
33 : #include <utils/foxtools/MFXSynchQue.h>
34 : #include <utils/gui/events/GUIEvent_Message.h>
35 : #include <utils/gui/windows/GUIAppEnum.h>
36 : #include <utils/gui/globjects/GUIGlObjectStorage.h>
37 : #include <utils/gui/images/GUITexturesHelper.h>
38 : #include <utils/xml/XMLSubSys.h>
39 : #include <guisim/GUINet.h>
40 : #include <guisim/GUIEventControl.h>
41 : #include <guisim/GUIVehicleControl.h>
42 : #include <netload/NLBuilder.h>
43 : #include <netload/NLHandler.h>
44 : #include <netload/NLJunctionControlBuilder.h>
45 : #include <guinetload/GUIEdgeControlBuilder.h>
46 : #include <guinetload/GUIDetectorBuilder.h>
47 : #include <guinetload/GUITriggerBuilder.h>
48 : #include <microsim/output/MSDetectorControl.h>
49 : #include <microsim/devices/MSDevice.h>
50 : #include <microsim/MSGlobals.h>
51 : #include <microsim/MSFrame.h>
52 : #include <microsim/MSRouteHandler.h>
53 : #include <mesogui/GUIMEVehicleControl.h>
54 : #include <libsumo/Helper.h>
55 : #include <traci-server/TraCIServer.h>
56 : #include "TraCIServerAPI_GUI.h"
57 : #include "GUIApplicationWindow.h"
58 : #include "GUILoadThread.h"
59 : #include "GUIGlobals.h"
60 : #include "GUIEvent_SimulationLoaded.h"
61 :
62 :
63 : // ===========================================================================
64 : // member method definitions
65 : // ===========================================================================
66 7533 : GUILoadThread::GUILoadThread(FXApp* app, GUIApplicationWindow* mw,
67 7533 : MFXSynchQue<GUIEvent*>& eq, FXEX::MFXThreadEvent& ev, const bool isLibsumo)
68 7533 : : MFXSingleEventThread(app, mw), myParent(mw), myEventQue(eq),
69 7533 : myEventThrow(ev), myAmLibsumo(isLibsumo) {
70 7533 : myErrorRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_ERROR);
71 7533 : myMessageRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_MESSAGE);
72 7533 : myWarningRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_WARNING);
73 7533 : MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
74 7533 : }
75 :
76 :
77 15046 : GUILoadThread::~GUILoadThread() {
78 7523 : delete myErrorRetriever;
79 7523 : delete myMessageRetriever;
80 7523 : delete myWarningRetriever;
81 15046 : }
82 :
83 :
84 : FXint
85 7533 : GUILoadThread::run() {
86 : // register message callbacks
87 7533 : MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
88 7533 : MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
89 15066 : if (!OptionsCont::getOptions().getBool("no-warnings")) {
90 7533 : MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
91 : }
92 :
93 : // try to load the given configuration
94 7533 : OptionsCont& oc = OptionsCont::getOptions();
95 : try {
96 7533 : if (myFile != "") {
97 : // triggered by menu option or reload
98 0 : oc.clear();
99 0 : MSFrame::fillOptions();
100 0 : oc.setByRootElement(OptionsIO::getRoot(myFile), myFile);
101 0 : oc.resetWritable(); // there may be command line options
102 0 : OptionsIO::getOptions();
103 : } else {
104 : // triggered at application start
105 7533 : OptionsIO::loadConfiguration();
106 15062 : if (oc.isSet("configuration-file")) {
107 293 : myFile = oc.getString("configuration-file");
108 293 : myParent->addRecentConfig(FXPath::absolute(myFile.c_str()));
109 :
110 14476 : } else if (oc.isSet("net-file")) {
111 7238 : myFile = oc.getString("net-file");
112 7238 : myParent->addRecentNetwork(FXPath::absolute(myFile.c_str()));
113 : }
114 15062 : myEventQue.push_back(new GUIEvent_Message("Loading '" + myFile + "'."));
115 7531 : myEventThrow.signal();
116 : }
117 7531 : myTitle = myFile;
118 7531 : if (!myAmLibsumo) {
119 : // within gui-based applications, nothing is reported to the console
120 7049 : MsgHandler::getMessageInstance()->removeRetriever(&OutputDevice::getDevice("stdout"));
121 7049 : MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
122 14098 : MsgHandler::getErrorInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
123 : }
124 : // do this once again to get parsed options
125 8193 : if (oc.getBool("duration-log.statistics") && oc.isDefault("verbose")) {
126 : // must be done before calling initOutputOptions (which checks option "verbose")
127 : // but initOutputOptions must come before checkOptions (so that warnings are printed)
128 1254 : oc.setDefault("verbose", "true");
129 : }
130 7531 : MsgHandler::initOutputOptions();
131 7531 : if (!MSFrame::checkOptions()) {
132 20 : throw ProcessError();
133 : }
134 22521 : XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
135 15014 : GUIGlobals::gRunAfterLoad = oc.getBool("start") || (myAmLibsumo && std::getenv("LIBSUMO_GUI") != nullptr);
136 7507 : GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
137 7507 : GUIGlobals::gDemoAutoReload = oc.getBool("demo");
138 7507 : GUIGlobals::gTrackerInterval = STEPS2TIME(string2time(oc.getString("tracker-interval")));
139 26 : } catch (ProcessError& e) {
140 38 : if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
141 12 : WRITE_ERROR(e.what());
142 : }
143 : // the options are not valid but maybe we want to quit
144 26 : GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
145 52 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
146 26 : submitEndAndCleanup(nullptr, 0, 0);
147 : return 0;
148 26 : }
149 :
150 : // initialise global settings
151 7507 : NLBuilder::initRandomness();
152 7507 : MSFrame::setMSGlobals(oc);
153 7507 : GUITexturesHelper::allowTextures(!oc.getBool("disable-textures"));
154 :
155 : MSVehicleControl* vehControl = nullptr;
156 7507 : GUIVisualizationSettings::UseMesoSim = MSGlobals::gUseMesoSim;
157 7507 : if (MSGlobals::gUseMesoSim) {
158 2485 : vehControl = new GUIMEVehicleControl();
159 : } else {
160 5022 : vehControl = new GUIVehicleControl();
161 : }
162 :
163 : GUINet* net = nullptr;
164 : SUMOTime simStartTime = 0;
165 : SUMOTime simEndTime = 0;
166 : std::vector<std::string> guiSettingsFiles;
167 : bool osgView = false;
168 : GUIEdgeControlBuilder* eb = nullptr;
169 : try {
170 : net = new GUINet(
171 : vehControl,
172 7507 : new GUIEventControl(),
173 7507 : new GUIEventControl(),
174 15014 : new GUIEventControl());
175 : // need to init TraCI-Server before loading routes to catch VehicleState::BUILT
176 : std::map<int, TraCIServer::CmdExecutor> execs;
177 7507 : execs[libsumo::CMD_GET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processGet;
178 7507 : execs[libsumo::CMD_SET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processSet;
179 7507 : TraCIServer::openSocket(execs);
180 7505 : if (myAmLibsumo) {
181 482 : libsumo::Helper::registerStateListener();
182 : }
183 :
184 7505 : eb = new GUIEdgeControlBuilder();
185 7505 : GUIDetectorBuilder db(*net);
186 7505 : NLJunctionControlBuilder jb(*net, db);
187 7505 : GUITriggerBuilder tb;
188 7505 : NLHandler handler("", *net, db, tb, *eb, jb);
189 7505 : tb.setHandler(&handler);
190 7505 : NLBuilder builder(oc, *net, *eb, jb, db, handler);
191 7505 : MsgHandler::getErrorInstance()->clear();
192 7505 : MsgHandler::getWarningInstance()->clear();
193 7505 : MsgHandler::getMessageInstance()->clear();
194 7505 : if (!builder.build()) {
195 228 : throw ProcessError();
196 : } else {
197 7256 : net->initGUIStructures();
198 7256 : simStartTime = string2time(oc.getString("begin"));
199 7256 : simEndTime = string2time(oc.getString("end"));
200 7256 : guiSettingsFiles = oc.getStringVector("gui-settings-file");
201 : #ifdef HAVE_OSG
202 7256 : osgView = oc.getBool("osg-view");
203 : #endif
204 14512 : if (oc.isSet("edgedata-files")) {
205 0 : if (!oc.isUsableFileList("edgedata-files")) {
206 0 : WRITE_ERRORF(TL("Could not load edgedata-files '%'"), oc.getString("edgedata-files"));
207 : } else {
208 0 : for (const std::string& file : oc.getStringVector("edgedata-files")) {
209 0 : net->loadEdgeData(file);
210 : }
211 : }
212 : }
213 : }
214 8752 : } catch (ProcessError& e) {
215 297 : if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
216 46 : WRITE_ERROR(e.what());
217 : }
218 251 : MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
219 251 : delete net;
220 : net = nullptr;
221 : #ifndef _DEBUG
222 251 : } catch (std::exception& e) {
223 0 : WRITE_ERROR(e.what());
224 0 : delete net;
225 : net = nullptr;
226 : #endif
227 0 : }
228 7507 : if (net == nullptr) {
229 251 : MSNet::clearAll();
230 : }
231 7507 : delete eb;
232 7507 : submitEndAndCleanup(net, simStartTime, simEndTime, guiSettingsFiles, osgView,
233 7507 : oc.getBool("registry-viewport"));
234 : return 0;
235 7507 : }
236 :
237 :
238 : void
239 7533 : GUILoadThread::submitEndAndCleanup(GUINet* net,
240 : const SUMOTime simStartTime,
241 : const SUMOTime simEndTime,
242 : const std::vector<std::string>& guiSettingsFiles,
243 : const bool osgView,
244 : const bool viewportFromRegistry) {
245 : // remove message callbacks
246 7533 : MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
247 7533 : MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
248 7533 : MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
249 : // inform parent about the process
250 7533 : GUIEvent* e = new GUIEvent_SimulationLoaded(net, simStartTime, simEndTime, myTitle, guiSettingsFiles, osgView, viewportFromRegistry);
251 7533 : myEventQue.push_back(e);
252 7533 : myEventThrow.signal();
253 7533 : }
254 :
255 :
256 : void
257 7533 : GUILoadThread::loadConfigOrNet(const std::string& file) {
258 7533 : myFile = file;
259 7533 : if (myFile != "") {
260 0 : OptionsIO::setArgs(0, nullptr);
261 : }
262 7533 : start();
263 7533 : }
264 :
265 :
266 : void
267 37231 : GUILoadThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
268 37231 : GUIEvent* e = new GUIEvent_Message(type, msg);
269 37231 : myEventQue.push_back(e);
270 37231 : myEventThrow.signal();
271 37231 : }
272 :
273 :
274 : const std::string&
275 1814959 : GUILoadThread::getFileName() const {
276 1814959 : return myFile;
277 : }
278 :
279 :
280 : /****************************************************************************/
|