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-2022 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(TL("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 bool needStart = false;
312 if (std::getenv("LIBSUMO_GUI") != nullptr) {
313 needStart = true;
314 for (const std::string& a : cmd) {
315 if (a == "-S" || a == "--start") {
316 needStart = false;
317 }
318 }
319 }
320 int origArgc = (int)cmd.size();
321 int argc = origArgc;
322 if (needStart) {
323 argc++;
324 }
325 char** argv = new char* [argc];
326 int i;
327 for (i = 0; i < origArgc; i++) {
328 argv[i] = new char[cmd[i].size() + 1];
329 std::strcpy(argv[i], cmd[i].c_str());
330 }
331 if (needStart) {
332 argv[i++] = (char*)"-S";
333 }
334 // make the output aware of threading
336 gSimulation = true;
339 OptionsIO::setArgs(argc, argv);
342 // Open display
343 myApp = new FXApp("SUMO GUI", "sumo-gui");
344 myApp->init(argc, argv);
345 int minor, major;
346 if (!FXGLVisual::supported(myApp, major, minor)) {
347 throw ProcessError("This system has no OpenGL support. Exiting.");
348 }
349
350 // build the main window
351 myWindow = new GUIApplicationWindow(myApp, "*.sumo.cfg,*.sumocfg");
352 gSchemeStorage.init(myApp);
353 myWindow->dependentBuild(true);
354 myApp->create();
355 myWindow->getRunner()->enableLibsumo();
356 // Load configuration given on command line
357 if (argc > 1) {
358 myWindow->loadOnStartup(true);
359 }
360 } catch (ProcessError& e) {
361 throw TraCIException(e.what());
362 }
363 return true;
364#endif
365}
366
367
368bool
369GUI::load(const std::vector<std::string>& /* cmd */) {
370 if (myWindow != nullptr) {
371 WRITE_ERROR(TL("libsumo.load is not implemented for the GUI."));
372 return true;
373 }
374 return false;
375}
376
377
378bool
379GUI::hasInstance() {
380 return myWindow != nullptr;
381}
382
383
384bool
385GUI::step(SUMOTime t) {
386 if (myWindow != nullptr) {
387 if (t == 0) {
388 t = SIMSTEP + DELTA_T;
389 }
390 while (SIMSTEP < t) {
391 myWindow->getRunner()->tryStep();
392 }
393 return true;
394 }
395 return false;
396}
397
398
399bool
400GUI::close(const std::string& /*reason*/) {
401 if (myWindow != nullptr) {
402 myApp->stop();
403 delete myWindow;
404 myWindow = nullptr;
406 delete myApp;
407 return true;
408 }
409 return false;
410}
411
412
414GUI::getView(const std::string& id) {
415 // we cannot use myWindow here, this is not set for the traci server
417 if (mw == nullptr) {
418 throw TraCIException("GUI is not running, command not implemented in command line sumo");
419 }
420 GUIGlChildWindow* const c = mw->getViewByID(id);
421 if (c == nullptr) {
422 throw TraCIException("View '" + id + "' is not known");
423 }
424 return c->getView();
425}
426
427
428std::shared_ptr<VariableWrapper>
429GUI::makeWrapper() {
430 return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
431}
432
433
434bool
435GUI::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* /* paramData */) {
436 switch (variable) {
437 case TRACI_ID_LIST:
438 return wrapper->wrapStringList(objID, variable, getIDList());
439 case ID_COUNT:
440 return wrapper->wrapInt(objID, variable, getIDCount());
441 case VAR_VIEW_ZOOM:
442 return wrapper->wrapDouble(objID, variable, getZoom(objID));
443 case VAR_VIEW_OFFSET:
444 return wrapper->wrapPosition(objID, variable, getOffset(objID));
445 case VAR_VIEW_SCHEMA:
446 return wrapper->wrapString(objID, variable, getSchema(objID));
447 case VAR_ANGLE:
448 return wrapper->wrapDouble(objID, variable, getAngle(objID));
450 return wrapper->wrapPositionVector(objID, variable, getBoundary(objID));
451 case VAR_HAS_VIEW:
452 return wrapper->wrapInt(objID, variable, hasView(objID) ? 1 : 0);
454 return wrapper->wrapString(objID, variable, getTrackedVehicle(objID));
455 default:
456 return false;
457 }
458}
459
460}
461
462
463/****************************************************************************/
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:274
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
SUMOTime DELTA_T
Definition: SUMOTime.cpp:37
#define SIMSTEP
Definition: SUMOTime.h:60
bool gSimulation
Definition: StdDefs.cpp:29
#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:1105
MSVehicleControl & getVehicleControl()
Returns the vehicle control.
Definition: MSNet.h:379
virtual MSTransportableControl & getPersonControl()
Returns the person control.
Definition: MSNet.cpp:1096
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:65
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:60
static void close()
Closes all of an applications subsystems.
static void init()
Initialises the xml-subsystem.
Definition: XMLSubSys.cpp:54
TRACI_CONST int TRACI_ID_LIST
TRACI_CONST int VAR_VIEW_BOUNDARY
std::map< std::string, libsumo::SubscriptionResults > ContextSubscriptionResults
Definition: TraCIDefs.h:301
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:300
TRACI_CONST int VAR_HAS_VIEW
TRACI_CONST int ID_COUNT
A 3D-position.
Definition: TraCIDefs.h:172
A list of positions.
Definition: TraCIDefs.h:215