Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/gui/GUILoadThread.cpp
169665 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-2025 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
GUILoadThread::GUILoadThread(FXApp* app, GUIApplicationWindow* mw,
67
MFXSynchQue<GUIEvent*>& eq, FXEX::MFXThreadEvent& ev, const bool isLibsumo)
68
: MFXSingleEventThread(app, mw), myParent(mw), myEventQue(eq),
69
myEventThrow(ev), myAmLibsumo(isLibsumo) {
70
myErrorRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_ERROR);
71
myMessageRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_MESSAGE);
72
myWarningRetriever = new MsgRetrievingFunction<GUILoadThread>(this, &GUILoadThread::retrieveMessage, MsgHandler::MsgType::MT_WARNING);
73
MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
74
}
75
76
77
GUILoadThread::~GUILoadThread() {
78
delete myErrorRetriever;
79
delete myMessageRetriever;
80
delete myWarningRetriever;
81
}
82
83
84
FXint
85
GUILoadThread::run() {
86
// register message callbacks
87
MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
88
MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
89
if (!OptionsCont::getOptions().getBool("no-warnings")) {
90
MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
91
}
92
93
// try to load the given configuration
94
OptionsCont& oc = OptionsCont::getOptions();
95
try {
96
if (myFile != "") {
97
// triggered by menu option or reload
98
oc.clear();
99
MSFrame::fillOptions();
100
oc.setByRootElement(OptionsIO::getRoot(myFile), myFile);
101
oc.resetWritable(); // there may be command line options
102
OptionsIO::getOptions();
103
} else {
104
// triggered at application start
105
OptionsIO::loadConfiguration();
106
if (oc.isSet("configuration-file")) {
107
myFile = oc.getString("configuration-file");
108
myParent->addRecentConfig(FXPath::absolute(myFile.c_str()));
109
110
} else if (oc.isSet("net-file")) {
111
myFile = oc.getString("net-file");
112
myParent->addRecentNetwork(FXPath::absolute(myFile.c_str()));
113
}
114
myEventQue.push_back(new GUIEvent_Message("Loading '" + myFile + "'."));
115
myEventThrow.signal();
116
}
117
myTitle = myFile;
118
if (!myAmLibsumo) {
119
// within gui-based applications, nothing is reported to the console
120
MsgHandler::getMessageInstance()->removeRetriever(&OutputDevice::getDevice("stdout"));
121
MsgHandler::getWarningInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
122
MsgHandler::getErrorInstance()->removeRetriever(&OutputDevice::getDevice("stderr"));
123
}
124
// do this once again to get parsed options
125
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
oc.setDefault("verbose", "true");
129
}
130
MsgHandler::initOutputOptions();
131
if (!MSFrame::checkOptions()) {
132
throw ProcessError();
133
}
134
XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
135
GUIGlobals::gRunAfterLoad = oc.getBool("start") || (myAmLibsumo && std::getenv("LIBSUMO_GUI") != nullptr);
136
GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
137
GUIGlobals::gDemoAutoReload = oc.getBool("demo");
138
GUIGlobals::gTrackerInterval = STEPS2TIME(string2time(oc.getString("tracker-interval")));
139
} catch (ProcessError& e) {
140
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
141
WRITE_ERROR(e.what());
142
}
143
// the options are not valid but maybe we want to quit
144
GUIGlobals::gQuitOnEnd = oc.getBool("quit-on-end");
145
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
146
submitEndAndCleanup(nullptr, 0, 0);
147
return 0;
148
}
149
150
// initialise global settings
151
NLBuilder::initRandomness();
152
MSFrame::setMSGlobals(oc);
153
GUITexturesHelper::allowTextures(!oc.getBool("disable-textures"));
154
155
MSVehicleControl* vehControl = nullptr;
156
GUIVisualizationSettings::UseMesoSim = MSGlobals::gUseMesoSim;
157
if (MSGlobals::gUseMesoSim) {
158
vehControl = new GUIMEVehicleControl();
159
} else {
160
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
new GUIEventControl(),
173
new GUIEventControl(),
174
new GUIEventControl());
175
// need to init TraCI-Server before loading routes to catch VehicleState::BUILT
176
std::map<int, TraCIServer::CmdExecutor> execs;
177
execs[libsumo::CMD_GET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processGet;
178
execs[libsumo::CMD_SET_GUI_VARIABLE] = &TraCIServerAPI_GUI::processSet;
179
TraCIServer::openSocket(execs);
180
if (myAmLibsumo) {
181
libsumo::Helper::registerStateListener();
182
}
183
184
eb = new GUIEdgeControlBuilder();
185
GUIDetectorBuilder db(*net);
186
NLJunctionControlBuilder jb(*net, db);
187
GUITriggerBuilder tb;
188
NLHandler handler("", *net, db, tb, *eb, jb);
189
tb.setHandler(&handler);
190
NLBuilder builder(oc, *net, *eb, jb, db, handler);
191
MsgHandler::getErrorInstance()->clear();
192
MsgHandler::getWarningInstance()->clear();
193
MsgHandler::getMessageInstance()->clear();
194
if (!builder.build()) {
195
throw ProcessError();
196
} else {
197
net->initGUIStructures();
198
simStartTime = string2time(oc.getString("begin"));
199
simEndTime = string2time(oc.getString("end"));
200
guiSettingsFiles = oc.getStringVector("gui-settings-file");
201
#ifdef HAVE_OSG
202
osgView = oc.getBool("osg-view");
203
#endif
204
if (oc.isSet("edgedata-files")) {
205
if (!oc.isUsableFileList("edgedata-files")) {
206
WRITE_ERRORF(TL("Could not load edgedata-files '%'"), oc.getString("edgedata-files"));
207
} else {
208
for (const std::string& file : oc.getStringVector("edgedata-files")) {
209
net->loadEdgeData(file);
210
}
211
}
212
}
213
}
214
} catch (ProcessError& e) {
215
if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
216
WRITE_ERROR(e.what());
217
}
218
MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
219
delete net;
220
net = nullptr;
221
#ifndef _DEBUG
222
} catch (std::exception& e) {
223
WRITE_ERROR(e.what());
224
delete net;
225
net = nullptr;
226
#endif
227
}
228
if (net == nullptr) {
229
MSNet::clearAll();
230
}
231
delete eb;
232
submitEndAndCleanup(net, simStartTime, simEndTime, guiSettingsFiles, osgView,
233
oc.getBool("registry-viewport"));
234
return 0;
235
}
236
237
238
void
239
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
MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
247
MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
248
MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
249
// inform parent about the process
250
GUIEvent* e = new GUIEvent_SimulationLoaded(net, simStartTime, simEndTime, myTitle, guiSettingsFiles, osgView, viewportFromRegistry);
251
myEventQue.push_back(e);
252
myEventThrow.signal();
253
}
254
255
256
void
257
GUILoadThread::loadConfigOrNet(const std::string& file) {
258
myFile = file;
259
if (myFile != "") {
260
OptionsIO::setArgs(0, nullptr);
261
}
262
start();
263
}
264
265
266
void
267
GUILoadThread::retrieveMessage(const MsgHandler::MsgType type, const std::string& msg) {
268
GUIEvent* e = new GUIEvent_Message(type, msg);
269
myEventQue.push_back(e);
270
myEventThrow.signal();
271
}
272
273
274
const std::string&
275
GUILoadThread::getFileName() const {
276
return myFile;
277
}
278
279
280
/****************************************************************************/
281
282