Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/guisim/GUITrafficLightLogicWrapper.cpp
193808 views
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 GUITrafficLightLogicWrapper.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @author Laura Bieker
19
/// @date Oct/Nov 2003
20
///
21
// A wrapper for tl-logics to allow their visualisation and interaction
22
/****************************************************************************/
23
#include <config.h>
24
25
#include <cassert>
26
#include <utils/common/MsgHandler.h>
27
#include <utils/geom/GeomHelper.h>
28
#include <utils/gui/globjects/GUIGlObject.h>
29
#include <utils/gui/div/GLObjectValuePassConnector.h>
30
#include <utils/gui/windows/GUIAppEnum.h>
31
#include <utils/gui/images/GUIIconSubSys.h>
32
#include <utils/gui/div/GLHelper.h>
33
#include <utils/gui/div/GUIParameterTableWindow.h>
34
#include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
35
#include <utils/gui/div/GUIGlobalSelection.h>
36
#include <microsim/MSLane.h>
37
#include <microsim/traffic_lights/MSTrafficLightLogic.h>
38
#include <microsim/traffic_lights/MSTLLogicControl.h>
39
#include <microsim/traffic_lights/MSOffTrafficLightLogic.h>
40
#include <microsim/traffic_lights/MSActuatedTrafficLightLogic.h>
41
#include <microsim/traffic_lights/MSDelayBasedTrafficLightLogic.h>
42
#include <microsim/traffic_lights/NEMAController.h>
43
#include <microsim/traffic_lights/MSRailSignal.h>
44
#include <microsim/logging/FunctionBinding.h>
45
#include <microsim/logging/FuncBinding_StringParam.h>
46
#include <gui/GUIApplicationWindow.h>
47
#include <gui/GUITLLogicPhasesTrackerWindow.h>
48
#include <gui/GUIGlobals.h>
49
#include <utils/gui/globjects/GLIncludes.h>
50
#include <utils/gui/div/GUIDesigns.h>
51
52
#include "GUITrafficLightLogicWrapper.h"
53
#include "GUINet.h"
54
55
// ===========================================================================
56
// FOX callback mapping
57
// ===========================================================================
58
FXDEFMAP(GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu)
59
GUITrafficLightLogicWrapperPopupMenuMap[] = {
60
FXMAPFUNC(SEL_COMMAND, MID_SHOWPHASES, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowPhases),
61
FXMAPFUNC(SEL_COMMAND, MID_TRACKPHASES, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdBegin2TrackPhases),
62
FXMAPFUNC(SEL_COMMAND, MID_SHOW_DETECTORS, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowDetectors),
63
FXMAPFUNC(SEL_COMMAND, MID_SWITCH_OFF, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLS2Off),
64
FXMAPFUNCS(SEL_COMMAND, MID_SWITCH, MID_SWITCH + 20, GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLSLogic),
65
};
66
67
// Object implementation
68
FXIMPLEMENT(GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu, GUIGLObjectPopupMenu, GUITrafficLightLogicWrapperPopupMenuMap, ARRAYNUMBER(GUITrafficLightLogicWrapperPopupMenuMap))
69
70
71
// ===========================================================================
72
// method definitions
73
// ===========================================================================
74
/* -------------------------------------------------------------------------
75
* GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu - methods
76
* ----------------------------------------------------------------------- */
77
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::GUITrafficLightLogicWrapperPopupMenu(
78
GUIMainWindow& app, GUISUMOAbstractView& parent, GUIGlObject* o) :
79
GUIGLObjectPopupMenu(app, parent, o) {}
80
81
82
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::~GUITrafficLightLogicWrapperPopupMenu() {}
83
84
85
86
long
87
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdBegin2TrackPhases(
88
FXObject*, FXSelector, void*) {
89
assert(myObject->getType() == GLO_TLLOGIC);
90
static_cast<GUITrafficLightLogicWrapper*>(myObject)->begin2TrackPhases();
91
return 1;
92
}
93
94
95
long
96
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowPhases(
97
FXObject*, FXSelector, void*) {
98
assert(myObject->getType() == GLO_TLLOGIC);
99
static_cast<GUITrafficLightLogicWrapper*>(myObject)->showPhases();
100
return 1;
101
}
102
103
long
104
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdShowDetectors(
105
FXObject*, FXSelector, void*) {
106
assert(myObject->getType() == GLO_TLLOGIC);
107
GUITrafficLightLogicWrapper* w = static_cast<GUITrafficLightLogicWrapper*>(myObject);
108
MSActuatedTrafficLightLogic* act = dynamic_cast<MSActuatedTrafficLightLogic*>(&w->getTLLogic());
109
if (act != nullptr) {
110
act->setShowDetectors(!act->showDetectors());
111
} else {
112
MSDelayBasedTrafficLightLogic* db = dynamic_cast<MSDelayBasedTrafficLightLogic*>(&w->getTLLogic());
113
if (db != nullptr) {
114
db->setShowDetectors(!db->showDetectors());
115
} else {
116
NEMALogic* nema = dynamic_cast<NEMALogic*>(&w->getTLLogic());
117
if (nema != nullptr) {
118
nema->setShowDetectors(!nema->showDetectors());
119
}
120
}
121
}
122
myParent->update();
123
return 1;
124
}
125
126
long
127
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLS2Off(
128
FXObject*, FXSelector /*sel*/, void*) {
129
assert(myObject->getType() == GLO_TLLOGIC);
130
static_cast<GUITrafficLightLogicWrapper*>(myObject)->switchTLSLogic(-1);
131
myParent->update();
132
return 1;
133
}
134
135
136
long
137
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapperPopupMenu::onCmdSwitchTLSLogic(
138
FXObject*, FXSelector sel, void*) {
139
assert(myObject->getType() == GLO_TLLOGIC);
140
static_cast<GUITrafficLightLogicWrapper*>(myObject)->switchTLSLogic(FXSELID(sel) - MID_SWITCH);
141
myParent->update();
142
return 1;
143
}
144
145
146
147
/* -------------------------------------------------------------------------
148
* GUITrafficLightLogicWrapper - methods
149
* ----------------------------------------------------------------------- */
150
GUITrafficLightLogicWrapper::GUITrafficLightLogicWrapper(MSTLLogicControl& control, MSTrafficLightLogic& tll) :
151
GUIGlObject(GLO_TLLOGIC, tll.getID(), GUIIconSubSys::getIcon(GUIIcon::LOCATETLS)),
152
myTLLogicControl(control), myTLLogic(tll) {
153
}
154
155
156
GUITrafficLightLogicWrapper::~GUITrafficLightLogicWrapper() {}
157
158
159
GUIGLObjectPopupMenu*
160
GUITrafficLightLogicWrapper::getPopUpMenu(GUIMainWindow& app, GUISUMOAbstractView& parent) {
161
myApp = &app;
162
GUIGLObjectPopupMenu* ret = new GUITrafficLightLogicWrapperPopupMenu(app, parent, this);
163
buildPopupHeader(ret, app);
164
buildCenterPopupEntry(ret);
165
const MSTLLogicControl::TLSLogicVariants& vars = myTLLogicControl.get(myTLLogic.getID());
166
std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
167
if (logics.size() > 1) {
168
std::vector<MSTrafficLightLogic*>::const_iterator i;
169
int index = 0;
170
for (i = logics.begin(); i != logics.end(); ++i, ++index) {
171
if (!vars.isActive(*i) && dynamic_cast<MSOffTrafficLightLogic*>(*i) == nullptr) {
172
GUIDesigns::buildFXMenuCommand(ret, TLF("Switch to '%'", (*i)->getProgramID()),
173
GUIIconSubSys::getIcon(GUIIcon::FLAG_MINUS), ret, (FXSelector)(MID_SWITCH + index));
174
}
175
}
176
new FXMenuSeparator(ret);
177
}
178
MSOffTrafficLightLogic* offLogic = dynamic_cast<MSOffTrafficLightLogic*>(vars.getActive());
179
if (offLogic == nullptr) {
180
GUIDesigns::buildFXMenuCommand(ret, TL("Switch off"), GUIIconSubSys::getIcon(GUIIcon::FLAG_MINUS), ret, MID_SWITCH_OFF);
181
}
182
GUIDesigns::buildFXMenuCommand(ret, TL("Track Phases"), nullptr, ret, MID_TRACKPHASES);
183
GUIDesigns::buildFXMenuCommand(ret, TL("Show Phases"), nullptr, ret, MID_SHOWPHASES);
184
MSActuatedTrafficLightLogic* act = dynamic_cast<MSActuatedTrafficLightLogic*>(&myTLLogic);
185
if (act != nullptr) {
186
GUIDesigns::buildFXMenuCommand(ret, act->showDetectors() ? TL("Hide Detectors") : TL("Show Detectors"), nullptr, ret, MID_SHOW_DETECTORS);
187
}
188
MSDelayBasedTrafficLightLogic* db = dynamic_cast<MSDelayBasedTrafficLightLogic*>(&myTLLogic);
189
if (db != nullptr) {
190
GUIDesigns::buildFXMenuCommand(ret, db->showDetectors() ? TL("Hide Detectors") : TL("Show Detectors"), nullptr, ret, MID_SHOW_DETECTORS);
191
}
192
NEMALogic* nema = dynamic_cast<NEMALogic*>(&myTLLogic);
193
if (nema != nullptr) {
194
GUIDesigns::buildFXMenuCommand(ret, nema->showDetectors() ? TL("Hide Detectors") : TL("Show Detectors"), nullptr, ret, MID_SHOW_DETECTORS);
195
}
196
new FXMenuSeparator(ret);
197
MSTrafficLightLogic* tll = getActiveTLLogic();
198
buildNameCopyPopupEntry(ret);
199
buildSelectionPopupEntry(ret);
200
GUIDesigns::buildFXMenuCommand(ret, TLF("Phase: %", toString(tll->getCurrentPhaseIndex())), nullptr, nullptr, 0);
201
const std::string& name = tll->getCurrentPhaseDef().getName();
202
if (name != "") {
203
GUIDesigns::buildFXMenuCommand(ret, TLF("Phase name: %", name), nullptr, nullptr, 0);
204
}
205
new FXMenuSeparator(ret);
206
buildShowParamsPopupEntry(ret, false);
207
buildPositionCopyEntry(ret, app);
208
return ret;
209
}
210
211
212
void
213
GUITrafficLightLogicWrapper::begin2TrackPhases(GUIMainWindow* app) {
214
if (app != nullptr) {
215
myApp = app;
216
}
217
assert(myApp != nullptr);
218
GUITLLogicPhasesTrackerWindow* window =
219
new GUITLLogicPhasesTrackerWindow(*myApp, myTLLogic, *this,
220
new FuncBinding_StringParam<MSTLLogicControl, std::pair<SUMOTime, MSPhaseDefinition> >
221
(&MSNet::getInstance()->getTLSControl(), &MSTLLogicControl::getPhaseDef, myTLLogic.getID()));
222
window->create();
223
window->show();
224
}
225
226
227
void
228
GUITrafficLightLogicWrapper::showPhases() {
229
GUITLLogicPhasesTrackerWindow* window =
230
new GUITLLogicPhasesTrackerWindow(*myApp, myTLLogic, *this,
231
static_cast<MSSimpleTrafficLightLogic&>(myTLLogic).getPhases());
232
window->setBeginTime(0);
233
window->create();
234
window->show();
235
}
236
237
238
GUIParameterTableWindow*
239
GUITrafficLightLogicWrapper::getParameterWindow(GUIMainWindow& app,
240
GUISUMOAbstractView&) {
241
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
242
ret->mkItem(TL("tlLogic [id]"), false, myTLLogic.getID());
243
ret->mkItem(TL("type"), false, toString(myTLLogic.getLogicType()));
244
ret->mkItem(TL("program"), false, myTLLogic.getProgramID());
245
ret->mkItem(TL("phase"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentPhase));
246
ret->mkItem(TL("phase name"), true, new FunctionBindingString<GUITrafficLightLogicWrapper>(this, &GUITrafficLightLogicWrapper::getCurrentPhaseName));
247
ret->mkItem(TL("duration"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentDurationSeconds));
248
ret->mkItem(TL("minDur"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentMinDurSeconds));
249
ret->mkItem(TL("maxDur"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentMaxDurSeconds));
250
ret->mkItem(TL("running duration"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getRunningDurationSeconds));
251
ret->mkItem(TL("earliestEnd"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentEarliestEndSeconds));
252
ret->mkItem(TL("latestEnd"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentLatestEndSeconds));
253
ret->mkItem(TL("time in cycle"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getCurrentTimeInCycleSeconds));
254
ret->mkItem(TL("cycle time"), true, new FunctionBinding<GUITrafficLightLogicWrapper, int>(this, &GUITrafficLightLogicWrapper::getDefaultCycleTimeSeconds));
255
MSRailSignal* rs = dynamic_cast<MSRailSignal*>(&myTLLogic);
256
if (rs != nullptr) {
257
ret->mkItem(TL("req driveway"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getRequestedDriveWay));
258
ret->mkItem(TL("blocking"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getBlockingVehicleIDs));
259
ret->mkItem(TL("blocking driveways"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getBlockingDriveWayIDs));
260
ret->mkItem(TL("rival"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getRivalVehicleIDs));
261
ret->mkItem(TL("priority"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getPriorityVehicleIDs));
262
ret->mkItem(TL("constraint"), true, new FunctionBindingString<MSRailSignal>(rs, &MSRailSignal::getConstraintInfo));
263
}
264
// close building
265
ret->closeBuilding(&myTLLogic);
266
return ret;
267
}
268
269
270
Boundary
271
GUITrafficLightLogicWrapper::getCenteringBoundary() const {
272
Boundary ret;
273
const MSTrafficLightLogic::LaneVectorVector& lanes = myTLLogic.getLaneVectors();
274
for (MSTrafficLightLogic::LaneVectorVector::const_iterator i = lanes.begin(); i != lanes.end(); ++i) {
275
const MSTrafficLightLogic::LaneVector& lanes2 = (*i);
276
for (MSTrafficLightLogic::LaneVector::const_iterator j = lanes2.begin(); j != lanes2.end(); ++j) {
277
ret.add((*j)->getShape()[-1]);
278
}
279
}
280
ret.grow(20);
281
return ret;
282
}
283
284
const std::string
285
GUITrafficLightLogicWrapper::getOptionalName() const {
286
return myTLLogic.getParameter("name", "");
287
}
288
289
290
void
291
GUITrafficLightLogicWrapper::switchTLSLogic(int to) {
292
if (to == -1) {
293
myTLLogicControl.switchTo(myTLLogic.getID(), "off");
294
GUINet::getGUIInstance()->createTLWrapper(getActiveTLLogic());
295
} else {
296
const MSTLLogicControl::TLSLogicVariants& vars = myTLLogicControl.get(myTLLogic.getID());
297
std::vector<MSTrafficLightLogic*> logics = vars.getAllLogics();
298
myTLLogicControl.switchTo(myTLLogic.getID(), logics[to]->getProgramID());
299
}
300
}
301
302
303
int
304
GUITrafficLightLogicWrapper::getLinkIndex(const MSLink* const link) const {
305
return myTLLogic.getLinkIndex(link);
306
}
307
308
309
void
310
GUITrafficLightLogicWrapper::drawGL(const GUIVisualizationSettings& s) const {
311
if (s.gaming) {
312
if (!MSNet::getInstance()->getTLSControl().isActive(&myTLLogic) || myTLLogic.getPhases().size() == 0) {
313
return;
314
}
315
const std::string& curState = myTLLogic.getCurrentPhaseDef().getState();
316
if (curState.find_first_of("gG") == std::string::npos) {
317
// no link is 'green' at the moment. find those that turn green next
318
const MSTrafficLightLogic::Phases& phases = myTLLogic.getPhases();
319
int curPhaseIdx = myTLLogic.getCurrentPhaseIndex();
320
int phaseIdx = (curPhaseIdx + 1) % phases.size();
321
std::vector<int> nextGreen;
322
while (phaseIdx != curPhaseIdx) {
323
const std::string& state = phases[phaseIdx]->getState();
324
for (int linkIdx = 0; linkIdx < (int)state.size(); linkIdx++) {
325
if ((LinkState)state[linkIdx] == LINKSTATE_TL_GREEN_MINOR ||
326
(LinkState)state[linkIdx] == LINKSTATE_TL_GREEN_MAJOR) {
327
nextGreen.push_back(linkIdx);
328
}
329
}
330
if (nextGreen.size() > 0) {
331
break;
332
}
333
phaseIdx = (phaseIdx + 1) % phases.size();
334
}
335
// highlight nextGreen links
336
for (const int idx : nextGreen) {
337
for (const MSLane* const lane : myTLLogic.getLanesAt(idx)) {
338
GLHelper::pushMatrix();
339
// split circle in red and yellow
340
const Position& pos = lane->getShape().back();
341
glTranslated(pos.x(), pos.y(), GLO_MAX);
342
double rot = RAD2DEG(lane->getShape().angleAt2D((int)lane->getShape().size() - 2)) - 90;
343
glRotated(rot, 0, 0, 1);
344
GLHelper::setColor(s.getLinkColor(LINKSTATE_TL_RED));
345
GLHelper::drawFilledCircle(lane->getWidth() / 2., 8, -90, 90);
346
if (!isRailway(lane->getPermissions())) {
347
// no yellow half-cirlce in railway game
348
GLHelper::setColor(s.getLinkColor(LINKSTATE_TL_YELLOW_MAJOR));
349
GLHelper::drawFilledCircle(lane->getWidth() / 2., 8, 90, 270);
350
}
351
GLHelper::popMatrix();
352
}
353
}
354
}
355
}
356
}
357
358
MSTrafficLightLogic*
359
GUITrafficLightLogicWrapper::getActiveTLLogic() const {
360
return myTLLogicControl.getActive(myTLLogic.getID());
361
}
362
363
int
364
GUITrafficLightLogicWrapper::getCurrentPhase() const {
365
return getActiveTLLogic()->getCurrentPhaseIndex();
366
}
367
368
std::string
369
GUITrafficLightLogicWrapper::getCurrentPhaseName() const {
370
return getActiveTLLogic()->getCurrentPhaseDef().getName();
371
}
372
373
int
374
GUITrafficLightLogicWrapper::getCurrentDurationSeconds() const {
375
return (int)STEPS2TIME(getActiveTLLogic()->getCurrentPhaseDef().duration);
376
}
377
378
int
379
GUITrafficLightLogicWrapper::getCurrentMinDurSeconds() const {
380
return (int)STEPS2TIME(getActiveTLLogic()->getMinDur());
381
}
382
383
int
384
GUITrafficLightLogicWrapper::getCurrentMaxDurSeconds() const {
385
return (int)STEPS2TIME(getActiveTLLogic()->getMaxDur());
386
}
387
388
int
389
GUITrafficLightLogicWrapper::getCurrentEarliestEndSeconds() const {
390
const SUMOTime earliestEnd = getActiveTLLogic()->getEarliestEnd();
391
return earliestEnd == MSPhaseDefinition::UNSPECIFIED_DURATION ? -1 : (int)STEPS2TIME(earliestEnd);
392
}
393
394
int
395
GUITrafficLightLogicWrapper::getCurrentLatestEndSeconds() const {
396
const SUMOTime latestEnd = getActiveTLLogic()->getLatestEnd();
397
return latestEnd == MSPhaseDefinition::UNSPECIFIED_DURATION ? -1 : (int)STEPS2TIME(latestEnd);
398
}
399
400
int
401
GUITrafficLightLogicWrapper::getDefaultCycleTimeSeconds() const {
402
return (int)STEPS2TIME(getActiveTLLogic()->getDefaultCycleTime());
403
}
404
405
int
406
GUITrafficLightLogicWrapper::getCurrentTimeInCycleSeconds() const {
407
return (int)STEPS2TIME(getActiveTLLogic()->getTimeInCycle());
408
}
409
410
int
411
GUITrafficLightLogicWrapper::getRunningDurationSeconds() const {
412
return (int)STEPS2TIME(getActiveTLLogic()->getSpentDuration());
413
}
414
415
416
/****************************************************************************/
417
418