Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/mesogui/GUIMEVehicle.cpp
169666 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 GUIMEVehicle.cpp
15
/// @author Daniel Krajzewicz
16
/// @author Jakob Erdmann
17
/// @author Michael Behrisch
18
/// @date Sept 2002
19
///
20
// A MSVehicle extended by some values for usage within the gui
21
/****************************************************************************/
22
#include <config.h>
23
24
#include <utils/gui/globjects/GLIncludes.h>
25
#include <utils/gui/div/GLHelper.h>
26
#include <utils/gui/div/GUIParameterTableWindow.h>
27
#include <utils/gui/div/GUIGlobalSelection.h>
28
#include <utils/gui/div/GUIBaseVehicleHelper.h>
29
#include <utils/emissions/PollutantsInterface.h>
30
#include <utils/gui/settings/GUIVisualizationSettings.h>
31
#include <microsim/MSStop.h>
32
#include <microsim/MSParkingArea.h>
33
#include <microsim/logging/CastingFunctionBinding.h>
34
#include <microsim/logging/FunctionBinding.h>
35
#include <microsim/devices/MSVehicleDevice.h>
36
#include <guisim/GUILane.h>
37
38
#include "GUIMEVehicle.h"
39
40
41
// ===========================================================================
42
// method definitions
43
// ===========================================================================
44
#ifdef _MSC_VER
45
#pragma warning(push)
46
#pragma warning(disable: 4355) // mask warning about "this" in initializers
47
#endif
48
GUIMEVehicle::GUIMEVehicle(SUMOVehicleParameter* pars, ConstMSRoutePtr route,
49
MSVehicleType* type, const double speedFactor) :
50
MEVehicle(pars, route, type, speedFactor),
51
GUIBaseVehicle((MSBaseVehicle&) * this) {
52
}
53
#ifdef _MSC_VER
54
#pragma warning(pop)
55
#endif
56
57
58
GUIMEVehicle::~GUIMEVehicle() { }
59
60
61
GUIParameterTableWindow*
62
GUIMEVehicle::getParameterWindow(GUIMainWindow& app,
63
GUISUMOAbstractView&) {
64
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
65
// add items
66
ret->mkItem("edge [id]", true, new FunctionBindingString<GUIMEVehicle>(this, &GUIMEVehicle::getEdgeID));
67
ret->mkItem("segment [#]", true, new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getSegmentIndex));
68
ret->mkItem("queue [#]", true, new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getQueIndex));
69
ret->mkItem("position [m]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getPositionOnLane));
70
ret->mkItem("speed [m/s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getSpeed));
71
ret->mkItem("angle [degree]", true, new FunctionBinding<GUIMEVehicle, double>(this, &GUIBaseVehicle::getNaviDegree));
72
ret->mkItem("waiting time [s]", true,
73
new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getWaitingSeconds));
74
ret->mkItem("speed factor", false, getChosenSpeedFactor());
75
//ret->mkItem("time gap [s]", true,
76
// new FunctionBinding<GUIMEVehicle, double>(this, &MSVehicle::getTimeGap));
77
//ret->mkItem("waiting time [s]", true,
78
// new FunctionBinding<GUIMEVehicle, double>(this, &MSVehicle::getWaitingSeconds));
79
//ret->mkItem("impatience", true,
80
// new FunctionBinding<GUIMEVehicle, double>(this, &MSVehicle::getImpatience));
81
//ret->mkItem("last lane change [s]", true,
82
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getLastLaneChangeOffset));
83
ret->mkItem("desired depart [s]", false, time2string(getParameter().depart));
84
ret->mkItem("depart delay [s]", false, time2string(getDepartDelay()));
85
ret->mkItem("odometer [m]", true,
86
new FunctionBinding<GUIMEVehicle, double>(this, &MSBaseVehicle::getOdometer));
87
if (getParameter().repetitionNumber < std::numeric_limits<int>::max()) {
88
ret->mkItem("remaining [#]", false, (int) getParameter().repetitionNumber - getParameter().repetitionsDone);
89
}
90
if (getParameter().repetitionOffset > 0) {
91
ret->mkItem("insertion period [s]", false, time2string(getParameter().repetitionOffset));
92
}
93
if (getParameter().repetitionProbability > 0) {
94
ret->mkItem("insertion probability", false, getParameter().repetitionProbability);
95
}
96
if (getParameter().poissonRate > 0) {
97
ret->mkItem(TL("poisson rate"), false, getParameter().poissonRate);
98
}
99
//ret->mkItem("stop info", false, getStopInfo());
100
ret->mkItem("line", false, myParameter->line);
101
//ret->mkItem("CO2 [mg/s]", true,
102
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getCO2Emissions));
103
//ret->mkItem("CO [mg/s]", true,
104
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getCOEmissions));
105
//ret->mkItem("HC [mg/s]", true,
106
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getHCEmissions));
107
//ret->mkItem("NOx [mg/s]", true,
108
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getNOxEmissions));
109
//ret->mkItem("PMx [mg/s]", true,
110
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getPMxEmissions));
111
//ret->mkItem("fuel [ml/s]", true,
112
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getFuelConsumption));
113
//ret->mkItem("noise (Harmonoise) [dB]", true,
114
// new FunctionBinding<GUIMEVehicle, double>(this, &GUIMEVehicle::getHarmonoise_NoiseEmissions));
115
ret->mkItem("devices", false, getDeviceDescription());
116
//ret->mkItem("persons", true,
117
// new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getPersonNumber));
118
//ret->mkItem("containers", true,
119
// new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getContainerNumber));
120
// meso specific values
121
ret->mkItem("event time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getEventTimeSeconds));
122
ret->mkItem("entry time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getLastEntryTimeSeconds));
123
ret->mkItem("block time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getBlockTimeSeconds));
124
ret->mkItem("link penalty [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getCurrentLinkPenaltySeconds));
125
ret->mkItem("stop time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getCurrentStoppingTimeSeconds));
126
// close building
127
ret->closeBuilding(&getParameter());
128
return ret;
129
}
130
131
132
GUIParameterTableWindow*
133
GUIMEVehicle::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
134
GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myType->getID());
135
ret->mkItem("type", false, myType->getID());
136
ret->mkItem("length [m]", false, myType->getLength());
137
ret->mkItem("width [m]", false, myType->getWidth());
138
ret->mkItem("height [m]", false, myType->getHeight());
139
ret->mkItem("minGap [m]", false, myType->getMinGap());
140
ret->mkItem("vehicle class", false, SumoVehicleClassStrings.getString(myType->getVehicleClass()));
141
ret->mkItem("emission class", false, PollutantsInterface::getName(myType->getEmissionClass()));
142
ret->mkItem("mass [kg]", false, myType->getMass());
143
ret->mkItem("guiShape", false, getVehicleShapeName(myType->getGuiShape()));
144
ret->mkItem("maximum speed [m/s]", false, getMaxSpeed());
145
ret->mkItem("desired maximum speed [m/s]", false, getVehicleType().getDesiredMaxSpeed());
146
ret->mkItem("desired headway (tau) [s]", false, getVehicleType().getCarFollowModel().getHeadwayTime());
147
ret->mkItem("speedFactor", false, myType->getParameter().speedFactor.toStr(gPrecision));
148
ret->mkItem("person capacity", false, myType->getPersonCapacity());
149
ret->mkItem(TL("boarding time [s]"), false, STEPS2TIME(myType->getLoadingDuration(true)));
150
ret->mkItem("container capacity", false, myType->getContainerCapacity());
151
ret->mkItem(TL("loading time [s]"), false, STEPS2TIME(myType->getLoadingDuration(false)));
152
ret->closeBuilding(&(myType->getParameter()));
153
return ret;
154
}
155
156
157
void
158
GUIMEVehicle::drawAction_drawCarriageClass(const GUIVisualizationSettings& /* s */, double scaledLength, bool /* asImage */) const {
159
GUIBaseVehicleHelper::drawAction_drawVehicleAsBoxPlus(getVType().getWidth(), scaledLength);
160
}
161
162
163
double
164
GUIMEVehicle::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
165
switch (activeScheme) {
166
case 8:
167
return getSpeed();
168
case 9:
169
return 0; // by actionStep
170
case 10:
171
return getWaitingSeconds();
172
case 11:
173
return 0; // getAccumulatedWaitingSeconds
174
case 12:
175
return 0; // invalid getLastLaneChangeOffset();
176
case 13:
177
return getSegment()->getEdge().getVehicleMaxSpeed(this);
178
case 14:
179
return 0; // invalid getEmissions<PollutantsInterface::CO2>();
180
case 15:
181
return 0; // invalid getEmissions<PollutantsInterface::CO>();
182
case 16:
183
return 0; // invalid getEmissions<PollutantsInterface::PM_X>();
184
case 17:
185
return 0; // invalid getEmissions<PollutantsInterface::NO_X>();
186
case 18:
187
return 0; // invalid getEmissions<PollutantsInterface::HC>();
188
case 19:
189
return 0; // invalid getEmissions<PollutantsInterface::FUEL>();
190
case 20:
191
return 0; // invalid getHarmonoise_NoiseEmissions();
192
case 21: // reroute number
193
if (getNumberReroutes() == 0) {
194
return -1;
195
}
196
return getNumberReroutes();
197
case 22:
198
return gSelected.isSelected(GLO_VEHICLE, getGlID());
199
case 23:
200
return 0; // invalid getBestLaneOffset();
201
case 24:
202
return 0; // invalid getAcceleration();
203
case 25:
204
return 0; // invalid getTimeGapOnLane();
205
case 26:
206
return STEPS2TIME(getDepartDelay());
207
case 27:
208
return 0; // electricityConsumption
209
case 28:
210
return 0; // timeLossSeconds
211
case 29:
212
return 0; // getSpeedLat
213
}
214
return 0;
215
}
216
217
218
219
void
220
GUIMEVehicle::drawRouteHelper(const GUIVisualizationSettings& s, ConstMSRoutePtr r, bool future, bool noLoop, const RGBColor& col) const {
221
const double exaggeration = getExaggeration(s);
222
MSRouteIterator start = future ? myCurrEdge : r->begin();
223
MSRouteIterator i = start;
224
std::map<const MSLane*, int> repeatLane; // count repeated occurrences of the same edge
225
const double textSize = s.vehicleName.size / s.scale;
226
const int indexDigits = (int)toString(r->size()).size();
227
const bool s2 = s.secondaryShape;
228
for (; i != r->end(); ++i) {
229
const GUILane* lane = static_cast<GUILane*>((*i)->getLanes()[0]);
230
GLHelper::drawBoxLines(lane->getShape(s2), lane->getShapeRotations(s2), lane->getShapeLengths(s2), exaggeration);
231
if (s.showRouteIndex) {
232
std::string label = toString((int)(i - myCurrEdge));
233
const double laneAngle = lane->getShape(s2).angleAt2D(0);
234
Position pos = lane->getShape(s2).front() - Position(0, textSize * repeatLane[lane]) + Position(
235
(laneAngle >= -0.25 * M_PI && laneAngle < 0.75 * M_PI ? 1 : -1) * 0.4 * indexDigits * textSize, 0);
236
//GLHelper::drawText(label, pos, 1.0, textSize, s.vehicleName.color);
237
GLHelper::drawTextSettings(s.vehicleName, label, pos, s.scale, s.angle, 1.0);
238
}
239
if (noLoop && i != start && (*i) == (*start)) {
240
break;
241
}
242
repeatLane[lane]++;
243
}
244
drawStopLabels(s, noLoop, col);
245
drawParkingInfo(s);
246
}
247
248
249
double
250
GUIMEVehicle::getLastLaneChangeOffset() const {
251
// @todo possibly we could compute something reasonable here
252
return 0;
253
}
254
255
256
std::string
257
GUIMEVehicle::getStopInfo() const {
258
std::string result = "";
259
if (isParking()) {
260
result += "parking";
261
} else if (isStopped()) {
262
result += "stopped";
263
} else {
264
return "";
265
}
266
return result;
267
}
268
269
std::string
270
GUIMEVehicle::getEdgeID() const {
271
return getEdge()->getID();
272
}
273
274
275
void
276
GUIMEVehicle::selectBlockingFoes() const {
277
// @todo possibly we could compute something reasonable here
278
}
279
280
281
double
282
GUIMEVehicle::getExaggeration(const GUIVisualizationSettings& s) const {
283
return s.vehicleSize.getExaggeration(s, this);
284
}
285
286
287
Boundary
288
GUIMEVehicle::getCenteringBoundary() const {
289
// getPosition returns the start of the first lane, so we do not use it here
290
getEdge()->lock();
291
const double curTime = SIMTIME;
292
double vehiclePosition = 0.;
293
const MESegment* const segment = getSegment();
294
const int queIdx = getQueIndex();
295
if (segment != nullptr && queIdx != MESegment::PARKING_QUEUE) {
296
vehiclePosition = segment->getLength();
297
const std::vector<MEVehicle*>& queue = segment->getQueue(queIdx);
298
for (auto it = queue.rbegin(); it != queue.rend(); ++it) {
299
const MEVehicle* const v = *it;
300
const double intendedLeave = MIN2(v->getEventTimeSeconds(), v->getBlockTimeSeconds());
301
const double entry = v->getLastEntryTimeSeconds();
302
const double offset = segment->getLength() * (curTime - entry) / (intendedLeave - entry);
303
if (offset < vehiclePosition) {
304
vehiclePosition = offset;
305
}
306
if (v == this) {
307
break;
308
}
309
vehiclePosition -= v->getVehicleType().getLengthWithGap();
310
}
311
}
312
Boundary b;
313
const MSLane* const lane = getEdge()->getLanes()[queIdx == MESegment::PARKING_QUEUE ? 0 : queIdx];
314
b.add(lane->geometryPositionAtOffset(getPositionOnLane() + vehiclePosition));
315
b.grow(getVehicleType().getLength());
316
getEdge()->unlock();
317
return b;
318
}
319
320
Position
321
GUIMEVehicle::getVisualPosition(bool s2, const double offset) const {
322
if (isParking()) {
323
// meso vehicles do not enter/leave parkingAreas so we cannot call
324
// myStops.begin()->parkingarea->getVehiclePosition(*this);
325
326
// position beside the road
327
const MSLane* first = getEdge()->getLanes()[0];
328
PositionVector shp = first->getShape(s2);
329
shp.move2side(SUMO_const_laneWidth * (MSGlobals::gLefthand ? -1 : 1));
330
return shp.positionAtOffset((getPositionOnLane() + offset) * first->getLengthGeometryFactor(s2));
331
}
332
return MEVehicle::getPosition(offset);
333
}
334
335
bool
336
GUIMEVehicle::isSelected() const {
337
return gSelected.isSelected(GLO_VEHICLE, getGlID());
338
}
339
340
/****************************************************************************/
341
342