Eclipse SUMO - Simulation of Urban MObility
libsumo/GUI.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2017-2023 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/****************************************************************************/
18// C++ TraCI client API implementation
19/****************************************************************************/
20#include <config.h>
21
33#include <utils/xml/XMLSubSys.h>
35#include <gui/GUIRunThread.h>
36#include <guisim/GUIVehicle.h>
37#include <guisim/GUIPerson.h>
38#include <guisim/GUIContainer.h>
39#include <microsim/MSFrame.h>
40#include <microsim/MSNet.h>
43#include <libsumo/TraCIDefs.h>
44#include <libsumo/Helper.h>
45#include <libsumo/GUI.h>
46
47
48namespace libsumo {
49// ===========================================================================
50// static member initializations
51// ===========================================================================
52SubscriptionResults GUI::mySubscriptionResults;
53ContextSubscriptionResults GUI::myContextSubscriptionResults;
54GUIApplicationWindow* GUI::myWindow = nullptr;
55FXApp* GUI::myApp = nullptr;
56
57
58// ===========================================================================
59// static member definitions
60// ===========================================================================
61std::vector<std::string>
62GUI::getIDList() {
63 if (GUIMainWindow::getInstance() == nullptr) {
64 throw TraCIException("GUI is not running, command not implemented in command line sumo");
65 }
67}
68
69
70int
71GUI::getIDCount() {
72 if (GUIMainWindow::getInstance() == nullptr) {
73 throw TraCIException("GUI is not running, command not implemented in command line sumo");
74 }
75 return (int)GUIMainWindow::getInstance()->getViewIDs().size();
76}
77
78
79double
80GUI::getZoom(const std::string& viewID) {
81 return getView(viewID)->getChanger().getZoom();
82}
83
84
85double
86GUI::getAngle(const std::string& viewID) {
87 return getView(viewID)->getChanger().getRotation();
88}
89
90
92GUI::getOffset(const std::string& viewID) {
93 GUISUMOAbstractView* v = getView(viewID);
95 pos.x = v->getChanger().getXPos();
96 pos.y = v->getChanger().getYPos();
97 return pos;
98}
99
100
101std::string
102GUI::getSchema(const std::string& viewID) {
103 return getView(viewID)->getVisualisationSettings().name;
104}
105
106
108GUI::getBoundary(const std::string& viewID) {
109 const Boundary& b = getView(viewID)->getVisibleBoundary();
110 TraCIPositionVector tb;
111 TraCIPosition minV;
112 TraCIPosition maxV;
113 minV.x = b.xmin();
114 maxV.x = b.xmax();
115 minV.y = b.ymin();
116 maxV.y = b.ymax();
117 minV.z = b.zmin();
118 maxV.z = b.zmax();
119 tb.value.push_back(minV);
120 tb.value.push_back(maxV);
121 return tb;
122}
123
124
125void
126GUI::setZoom(const std::string& viewID, double zoom) {
127 GUISUMOAbstractView* const v = getView(viewID);
128 const Position off(v->getChanger().getXPos(), v->getChanger().getYPos(), v->getChanger().zoom2ZPos(zoom));
129 const Position p(off.x(), off.y(), 0);
131}
132
133
134void
135GUI::setAngle(const std::string& viewID, double angle) {
136 GUISUMOAbstractView* const v = getView(viewID);
137 const Position off(v->getChanger().getXPos(), v->getChanger().getYPos(), v->getChanger().getZPos());
138 const Position p(off.x(), off.y(), 0);
139 v->setViewportFromToRot(off, p, angle);
140}
141
142
143void
144GUI::setOffset(const std::string& viewID, double x, double y) {
145 GUISUMOAbstractView* const v = getView(viewID);
146 const Position off(x, y, v->getChanger().getZPos());
147 const Position p(x, y, 0);
149}
150
151
152void
153GUI::setSchema(const std::string& viewID, const std::string& schemeName) {
154 getView(viewID)->setColorScheme(schemeName);
155}
156
157
158void
159GUI::addView(const std::string& viewID, const std::string& schemeName, bool in3D) {
161 if (mw == nullptr) {
162 throw TraCIException("GUI is not running, command not implemented in command line sumo");
163 }
164 // calling openNewView directly doesn't work from the traci/simulation thread
165 mw->sendBlockingEvent(new GUIEvent_AddView(viewID, schemeName, in3D));
166 // sonar thinks here is a memory leak but the GUIApplicationWindow does the clean up
167} // NOSONAR
168
169
170void
171GUI::removeView(const std::string& viewID) {
173 if (mw == nullptr) {
174 throw TraCIException("GUI is not running, command not implemented in command line sumo");
175 }
176 // calling removeViewByID directly doesn't work from the traci/simulation thread
177 mw->sendBlockingEvent(new GUIEvent_CloseView(viewID));
178 // sonar thinks here is a memory leak but the GUIApplicationWindow does the clean up
179} // NOSONAR
180
181
182void
183GUI::setBoundary(const std::string& viewID, double xmin, double ymin, double xmax, double ymax) {
184 getView(viewID)->centerTo(Boundary(xmin, ymin, xmax, ymax));
185}
186
187
188void
189GUI::screenshot(const std::string& viewID, const std::string& filename, const int width, const int height) {
190 getView(viewID)->addSnapshot(SIMSTEP, filename, width, height);
191}
192
193
194void
195GUI::trackVehicle(const std::string& viewID, const std::string& vehID) {
196 GUISUMOAbstractView* const v = getView(viewID);
197 if (vehID == "") {
198 v->stopTrack();
199 } else {
200 GUIGlID glID = 0;
202 if (veh != nullptr) {
203 glID = static_cast<GUIVehicle*>(veh)->getGlID();
204 } else {
206 if (person != nullptr) {
207 glID = static_cast<GUIPerson*>(person)->getGlID();
208 } else {
210 if (container != nullptr) {
211 glID = static_cast<GUIContainer*>(container)->getGlID();
212 } else {
213 throw TraCIException("Could not find vehicle or person '" + vehID + "'.");
214 }
215 }
216 }
217 if (v->getTrackedID() != glID) {
218 v->startTrack(glID);
219 }
220 }
221}
222
223
224bool
225GUI::hasView(const std::string& viewID) {
227 if (mw == nullptr) {
228 throw TraCIException("GUI is not running, command not implemented in command line sumo");
229 }
230 return mw->getViewByID(viewID) != nullptr;
231}
232
233
234std::string
235GUI::getTrackedVehicle(const std::string& viewID) {
236 GUISUMOAbstractView* const v = getView(viewID);
237 GUIGlObject* tracked = nullptr;
238 const GUIGlID gid = v->getTrackedID();
239 if (gid != GUIGlObject::INVALID_ID) {
241 }
242 const std::string result = tracked == nullptr ? "" : tracked->getMicrosimID();
243 if (gid != GUIGlObject::INVALID_ID) {
245 }
246 return result;
247}
248
249
250void
251GUI::track(const std::string& objID, const std::string& viewID) {
252 trackVehicle(viewID, objID);
253}
254
255
256bool
257GUI::isSelected(const std::string& objID, const std::string& objType) {
258 const std::string fullName = objType + ":" + objID;
260 if (obj == nullptr) {
262 throw TraCIException("The " + objType + " " + objID + " is not known.");
263 }
264 const bool result = gSelected.isSelected(obj);
266 return result;
267}
268
269
270void
271GUI::toggleSelection(const std::string& objID, const std::string& objType) {
272 const std::string fullName = objType + ":" + objID;
274 if (obj == nullptr) {
276 throw TraCIException("The " + objType + " " + objID + " is not known.");
277 }
280}
281
282
283std::string
284GUI::getParameter(const std::string& /* viewID */, const std::string& /* name */) {
285 return "";
286}
287
288
289void
290GUI::setParameter(const std::string& /* viewID */, const std::string& /* name */, const std::string& /* value */) {
291}
292
293
296
297
298bool
299GUI::start(const std::vector<std::string>& cmd) {
300 if (cmd[0].find("sumo-gui") == std::string::npos && std::getenv("LIBSUMO_GUI") == nullptr) {
301 return false;
302 }
303#ifdef WIN32
304 WRITE_WARNING("Libsumo on Windows does not work with GUI, falling back to plain libsumo.");
305 return false;
306#else
307 try {
308 if (!GUI::close("Libsumo started new instance.")) {
309// SystemFrame::close();
310 }
311 int argc = 1;
312 char array[1][10] = {{0}};
313 strcpy(array[0], "dummy");
314 char* argv[1];
315 argv[0] = array[0];
316 // make the output aware of threading
318 gSimulation = true;
321 std::vector<std::string> args(cmd.begin() + 1, cmd.end());
322 OptionsIO::setArgs(args);
325 // Open display
326 myApp = new FXApp("SUMO GUI", "sumo-gui");
327 myApp->init(argc, argv);
328 int minor, major;
329 if (!FXGLVisual::supported(myApp, major, minor)) {
330 throw ProcessError(TL("This system has no OpenGL support. Exiting."));
331 }
332
333 // build the main window
334 myWindow = new GUIApplicationWindow(myApp, "*.sumo.cfg,*.sumocfg");
335 gSchemeStorage.init(myApp);
336 myWindow->dependentBuild(true);
337 myApp->create();
338 myWindow->getRunner()->enableLibsumo();
339 // Load configuration given on command line
340 myWindow->loadOnStartup(true);
341 } catch (ProcessError& e) {
342 throw TraCIException(e.what());
343 }
344 return true;
345#endif
346}
347
348
349bool
350GUI::load(const std::vector<std::string>& /* cmd */) {
351 if (myWindow != nullptr) {
352 WRITE_ERROR("libsumo.load is not implemented for the GUI.");
353 return true;
354 }
355 return false;
356}
357
358
359bool
360GUI::hasInstance() {
361 return myWindow != nullptr;
362}
363
364
365bool
366GUI::step(SUMOTime t) {
367 if (myWindow != nullptr) {
368 if (t == 0) {
369 t = SIMSTEP + DELTA_T;
370 }
371 while (SIMSTEP < t) {
372 myWindow->getRunner()->tryStep();
373 }
374 return true;
375 }
376 return false;
377}
378
379
380bool
381GUI::close(const std::string& /*reason*/) {
382 if (myWindow != nullptr) {
383 myApp->stop();
384 delete myWindow;
385 myWindow = nullptr;
387 delete myApp;
388 return true;
389 }
390 return false;
391}
392
393
395GUI::getView(const std::string& id) {
396 // we cannot use myWindow here, this is not set for the traci server
398 if (mw == nullptr) {
399 throw TraCIException("GUI is not running, command not implemented in command line sumo");
400 }
401 GUIGlChildWindow* const c = mw->getViewByID(id);
402 if (c == nullptr) {
403 throw TraCIException("View '" + id + "' is not known");
404 }
405 return c->getView();
406}
407
408
409std::shared_ptr<VariableWrapper>
410GUI::makeWrapper() {
411 return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
412}
413
414
415bool
416GUI::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* /* paramData */) {
417 switch (variable) {
418 case TRACI_ID_LIST:
419 return wrapper->wrapStringList(objID, variable, getIDList());
420 case ID_COUNT:
421 return wrapper->wrapInt(objID, variable, getIDCount());
422 case VAR_VIEW_ZOOM:
423 return wrapper->wrapDouble(objID, variable, getZoom(objID));
424 case VAR_VIEW_OFFSET:
425 return wrapper->wrapPosition(objID, variable, getOffset(objID));
426 case VAR_VIEW_SCHEMA:
427 return wrapper->wrapString(objID, variable, getSchema(objID));
428 case VAR_ANGLE:
429 return wrapper->wrapDouble(objID, variable, getAngle(objID));
431 return wrapper->wrapPositionVector(objID, variable, getBoundary(objID));
432 case VAR_HAS_VIEW:
433 return wrapper->wrapInt(objID, variable, hasView(objID) ? 1 : 0);
435 return wrapper->wrapString(objID, variable, getTrackedVehicle(objID));
436 default:
437 return false;
438 }
439}
440
441}
442
443
444/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
GUICompleteSchemeStorage gSchemeStorage
unsigned int GUIGlID
Definition: GUIGlObject.h:43
GUISelectedStorage gSelected
A global holder of selected objects.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:276
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:267
#define TL(string)
Definition: MsgHandler.h:284
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
#define SIMSTEP
Definition: SUMOTime.h:60
bool gSimulation
Definition: StdDefs.cpp:30
#define LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(CLASS, DOM)
Definition: TraCIDefs.h:76
#define LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(CLASS)
Definition: TraCIDefs.h:123
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:39
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:130
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:118
double zmin() const
Returns minimum z-coordinate.
Definition: Boundary.cpp:142
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:136
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:124
double zmax() const
Returns maximum z-coordinate.
Definition: Boundary.cpp:148
The main window of the SUMO-gui.
void init(FXApp *app, bool netedit=false)
Initialises the storage with some default settings.
GUISUMOAbstractView * getView() const
return GUISUMOAbstractView
const std::string & getMicrosimID() const
Returns the id of the object as known to microsim.
Definition: GUIGlObject.h:141
static const GUIGlID INVALID_ID
Definition: GUIGlObject.h:71
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:102
void unblockObject(GUIGlID id)
Marks an object as unblocked.
GUIGlObject * getObjectBlocking(GUIGlID id) const
Returns the object from the container locking it.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
C++ TraCI client API implementation.
GUIGlChildWindow * getViewByID(const std::string &id) const
get specific view by ID
std::vector< std::string > getViewIDs() const
get view IDs
static GUIMainWindow * getInstance()
get instance
virtual void sendBlockingEvent(GUIEvent *event)
Sends an event from the application thread to the GUI and waits until it is handled.
virtual double zoom2ZPos(double zoom) const =0
Returns the camera height at which the given zoom level is reached.
virtual double getRotation() const =0
Returns the rotation of the canvas stored in this changer.
virtual double getXPos() const =0
Returns the x-offset of the field to show stored in this changer.
virtual double getYPos() const =0
Returns the y-offset of the field to show stored in this changer.
virtual double getZPos() const =0
Returns the camera height corresponding to the current zoom factor.
GUIPerspectiveChanger & getChanger() const
get changer
virtual void setViewportFromToRot(const Position &lookFrom, const Position &lookAt, double rotation)
applies the given viewport settings
virtual void stopTrack()
stop track
virtual void startTrack(int)
star track
virtual GUIGlID getTrackedID() const
get tracked id
void toggleSelection(GUIGlID id)
Toggles selection of an object.
bool isSelected(GUIGlObjectType type, GUIGlID id)
Returns the information whether the object with the given type and id is selected.
A MSVehicle extended by some values for usage within the gui.
Definition: GUIVehicle.h:51
static void fillOptions()
Inserts options used by the simulation into the OptionsCont-singleton.
Definition: MSFrame.cpp:60
static MSNet * getInstance()
Returns the pointer to the unique instance of MSNet (singleton).
Definition: MSNet.cpp:183
virtual MSTransportableControl & getContainerControl()
Returns the container control.
Definition: MSNet.cpp:1168
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:378
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1159
MSTransportable * get(const std::string &id) const
Returns the named transportable, if existing.
SUMOVehicle * getVehicle(const std::string &id) const
Returns the vehicle with the given id.
static void setFactory(Factory func)
Sets the factory function to use for new MsgHandlers.
Definition: MsgHandler.h:64
static MsgHandler * create(MsgType type)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
bool processMetaOptions(bool missingOptions)
Checks for help and configuration output, returns whether we should exit.
static void setArgs(int argc, char **argv)
Stores the command line arguments for later parsing.
Definition: OptionsIO.cpp:58
static void getOptions(const bool commandLineOnly=false)
Parses the command line arguments and loads the configuration.
Definition: OptionsIO.cpp:74
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
Representation of a vehicle.
Definition: SUMOVehicle.h:62
static void close()
Closes all of an applications subsystems.
static void init()
Initialises the xml-subsystem.
Definition: XMLSubSys.cpp:55
TRACI_CONST int TRACI_ID_LIST
TRACI_CONST int VAR_VIEW_BOUNDARY
std::map< std::string, libsumo::SubscriptionResults > ContextSubscriptionResults
Definition: TraCIDefs.h:338
TRACI_CONST int VAR_ANGLE
TRACI_CONST int VAR_VIEW_OFFSET
TRACI_CONST int VAR_VIEW_SCHEMA
TRACI_CONST int VAR_VIEW_ZOOM
TRACI_CONST int VAR_TRACK_VEHICLE
std::map< std::string, libsumo::TraCIResults > SubscriptionResults
{object->{variable->value}}
Definition: TraCIDefs.h:337
TRACI_CONST int VAR_HAS_VIEW
TRACI_CONST int ID_COUNT
@ array
array (ordered collection of values)
A 2D or 3D-position, for 2D positions z == INVALID_DOUBLE_VALUE.
Definition: TraCIDefs.h:178
A list of positions.
Definition: TraCIDefs.h:234