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