Line data Source code
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 295465 : GUIMEVehicle::GUIMEVehicle(SUMOVehicleParameter* pars, ConstMSRoutePtr route,
49 295465 : MSVehicleType* type, const double speedFactor) :
50 : MEVehicle(pars, route, type, speedFactor),
51 590930 : GUIBaseVehicle((MSBaseVehicle&) * this) {
52 295465 : }
53 : #ifdef _MSC_VER
54 : #pragma warning(pop)
55 : #endif
56 :
57 :
58 590920 : GUIMEVehicle::~GUIMEVehicle() { }
59 :
60 :
61 : GUIParameterTableWindow*
62 0 : GUIMEVehicle::getParameterWindow(GUIMainWindow& app,
63 : GUISUMOAbstractView&) {
64 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
65 : // add items
66 0 : ret->mkItem("edge [id]", true, new FunctionBindingString<GUIMEVehicle>(this, &GUIMEVehicle::getEdgeID));
67 0 : ret->mkItem("segment [#]", true, new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getSegmentIndex));
68 0 : ret->mkItem("queue [#]", true, new FunctionBinding<GUIMEVehicle, int>(this, &GUIMEVehicle::getQueIndex));
69 0 : ret->mkItem("position [m]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getPositionOnLane));
70 0 : ret->mkItem("speed [m/s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getSpeed));
71 0 : ret->mkItem("angle [degree]", true, new FunctionBinding<GUIMEVehicle, double>(this, &GUIBaseVehicle::getNaviDegree));
72 0 : ret->mkItem("waiting time [s]", true,
73 0 : new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getWaitingSeconds));
74 0 : 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 0 : ret->mkItem("desired depart [s]", false, time2string(getParameter().depart));
84 0 : ret->mkItem("depart delay [s]", false, time2string(getDepartDelay()));
85 0 : ret->mkItem("odometer [m]", true,
86 0 : new FunctionBinding<GUIMEVehicle, double>(this, &MSBaseVehicle::getOdometer));
87 0 : if (getParameter().repetitionNumber < std::numeric_limits<int>::max()) {
88 0 : ret->mkItem("remaining [#]", false, (int) getParameter().repetitionNumber - getParameter().repetitionsDone);
89 : }
90 0 : if (getParameter().repetitionOffset > 0) {
91 0 : ret->mkItem("insertion period [s]", false, time2string(getParameter().repetitionOffset));
92 : }
93 0 : if (getParameter().repetitionProbability > 0) {
94 0 : ret->mkItem("insertion probability", false, getParameter().repetitionProbability);
95 : }
96 0 : if (getParameter().poissonRate > 0) {
97 0 : ret->mkItem(TL("poisson rate"), false, getParameter().poissonRate);
98 : }
99 : //ret->mkItem("stop info", false, getStopInfo());
100 0 : 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 0 : 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 0 : ret->mkItem("event time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getEventTimeSeconds));
122 0 : ret->mkItem("entry time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getLastEntryTimeSeconds));
123 0 : ret->mkItem("block time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getBlockTimeSeconds));
124 0 : ret->mkItem("link penalty [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getCurrentLinkPenaltySeconds));
125 0 : ret->mkItem("stop time [s]", true, new FunctionBinding<GUIMEVehicle, double>(this, &MEVehicle::getCurrentStoppingTimeSeconds));
126 : // close building
127 0 : ret->closeBuilding(&getParameter());
128 0 : return ret;
129 : }
130 :
131 :
132 : GUIParameterTableWindow*
133 0 : GUIMEVehicle::getTypeParameterWindow(GUIMainWindow& app, GUISUMOAbstractView&) {
134 0 : GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this, "vType:" + myType->getID());
135 0 : ret->mkItem("type", false, myType->getID());
136 0 : ret->mkItem("length [m]", false, myType->getLength());
137 0 : ret->mkItem("width [m]", false, myType->getWidth());
138 0 : ret->mkItem("height [m]", false, myType->getHeight());
139 0 : ret->mkItem("minGap [m]", false, myType->getMinGap());
140 0 : ret->mkItem("vehicle class", false, SumoVehicleClassStrings.getString(myType->getVehicleClass()));
141 0 : ret->mkItem("emission class", false, PollutantsInterface::getName(myType->getEmissionClass()));
142 0 : ret->mkItem("mass [kg]", false, myType->getMass());
143 0 : ret->mkItem("guiShape", false, getVehicleShapeName(myType->getGuiShape()));
144 0 : ret->mkItem("maximum speed [m/s]", false, getMaxSpeed());
145 0 : ret->mkItem("desired maximum speed [m/s]", false, getVehicleType().getDesiredMaxSpeed());
146 0 : ret->mkItem("desired headway (tau) [s]", false, getVehicleType().getCarFollowModel().getHeadwayTime());
147 0 : ret->mkItem("speedFactor", false, myType->getParameter().speedFactor.toStr(gPrecision));
148 0 : ret->mkItem("person capacity", false, myType->getPersonCapacity());
149 0 : ret->mkItem(TL("boarding time [s]"), false, STEPS2TIME(myType->getLoadingDuration(true)));
150 0 : ret->mkItem("container capacity", false, myType->getContainerCapacity());
151 0 : ret->mkItem(TL("loading time [s]"), false, STEPS2TIME(myType->getLoadingDuration(false)));
152 0 : ret->closeBuilding(&(myType->getParameter()));
153 0 : return ret;
154 : }
155 :
156 :
157 : void
158 0 : GUIMEVehicle::drawAction_drawCarriageClass(const GUIVisualizationSettings& /* s */, double scaledLength, bool /* asImage */) const {
159 0 : GUIBaseVehicleHelper::drawAction_drawVehicleAsBoxPlus(getVType().getWidth(), scaledLength);
160 0 : }
161 :
162 :
163 : double
164 1232787 : GUIMEVehicle::getColorValue(const GUIVisualizationSettings& /* s */, int activeScheme) const {
165 1232787 : switch (activeScheme) {
166 0 : case 8:
167 0 : return getSpeed();
168 : case 9:
169 : return 0; // by actionStep
170 0 : case 10:
171 0 : return getWaitingSeconds();
172 : case 11:
173 : return 0; // getAccumulatedWaitingSeconds
174 : case 12:
175 : return 0; // invalid getLastLaneChangeOffset();
176 0 : case 13:
177 0 : 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 0 : case 21: // reroute number
193 0 : if (getNumberReroutes() == 0) {
194 : return -1;
195 : }
196 0 : return getNumberReroutes();
197 0 : case 22:
198 0 : 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 0 : case 26:
206 0 : 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 0 : GUIMEVehicle::drawRouteHelper(const GUIVisualizationSettings& s, ConstMSRoutePtr r, bool future, bool noLoop, const RGBColor& col) const {
221 0 : const double exaggeration = getExaggeration(s);
222 0 : 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 0 : const double textSize = s.vehicleName.size / s.scale;
226 0 : const int indexDigits = (int)toString(r->size()).size();
227 0 : const bool s2 = s.secondaryShape;
228 0 : for (; i != r->end(); ++i) {
229 0 : const GUILane* lane = static_cast<GUILane*>((*i)->getLanes()[0]);
230 0 : GLHelper::drawBoxLines(lane->getShape(s2), lane->getShapeRotations(s2), lane->getShapeLengths(s2), exaggeration);
231 0 : if (s.showRouteIndex) {
232 0 : std::string label = toString((int)(i - myCurrEdge));
233 0 : const double laneAngle = lane->getShape(s2).angleAt2D(0);
234 0 : Position pos = lane->getShape(s2).front() - Position(0, textSize * repeatLane[lane]) + Position(
235 0 : (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 0 : GLHelper::drawTextSettings(s.vehicleName, label, pos, s.scale, s.angle, 1.0);
238 : }
239 0 : if (noLoop && i != start && (*i) == (*start)) {
240 : break;
241 : }
242 0 : repeatLane[lane]++;
243 : }
244 0 : drawStopLabels(s, noLoop, col);
245 0 : drawParkingInfo(s);
246 0 : }
247 :
248 :
249 : double
250 0 : GUIMEVehicle::getLastLaneChangeOffset() const {
251 : // @todo possibly we could compute something reasonable here
252 0 : return 0;
253 : }
254 :
255 :
256 : std::string
257 0 : GUIMEVehicle::getStopInfo() const {
258 0 : std::string result = "";
259 0 : if (isParking()) {
260 : result += "parking";
261 0 : } else if (isStopped()) {
262 : result += "stopped";
263 : } else {
264 0 : return "";
265 : }
266 0 : return result;
267 : }
268 :
269 : std::string
270 0 : GUIMEVehicle::getEdgeID() const {
271 0 : return getEdge()->getID();
272 : }
273 :
274 :
275 : void
276 0 : GUIMEVehicle::selectBlockingFoes() const {
277 : // @todo possibly we could compute something reasonable here
278 0 : }
279 :
280 :
281 : double
282 1279943 : GUIMEVehicle::getExaggeration(const GUIVisualizationSettings& s) const {
283 1279943 : return s.vehicleSize.getExaggeration(s, this);
284 : }
285 :
286 :
287 : Boundary
288 0 : GUIMEVehicle::getCenteringBoundary() const {
289 : // getPosition returns the start of the first lane, so we do not use it here
290 0 : getEdge()->lock();
291 0 : const double curTime = SIMTIME;
292 : double vehiclePosition = 0.;
293 : const MESegment* const segment = getSegment();
294 : const int queIdx = getQueIndex();
295 0 : if (segment != nullptr && queIdx != MESegment::PARKING_QUEUE) {
296 : vehiclePosition = segment->getLength();
297 : const std::vector<MEVehicle*>& queue = segment->getQueue(queIdx);
298 0 : for (auto it = queue.rbegin(); it != queue.rend(); ++it) {
299 0 : const MEVehicle* const v = *it;
300 : const double intendedLeave = MIN2(v->getEventTimeSeconds(), v->getBlockTimeSeconds());
301 : const double entry = v->getLastEntryTimeSeconds();
302 0 : const double offset = segment->getLength() * (curTime - entry) / (intendedLeave - entry);
303 0 : if (offset < vehiclePosition) {
304 : vehiclePosition = offset;
305 : }
306 0 : if (v == this) {
307 : break;
308 : }
309 0 : vehiclePosition -= v->getVehicleType().getLengthWithGap();
310 : }
311 : }
312 0 : Boundary b;
313 0 : const MSLane* const lane = getEdge()->getLanes()[queIdx == MESegment::PARKING_QUEUE ? 0 : queIdx];
314 0 : b.add(lane->geometryPositionAtOffset(getPositionOnLane() + vehiclePosition));
315 0 : b.grow(getVehicleType().getLength());
316 0 : getEdge()->unlock();
317 0 : return b;
318 : }
319 :
320 : Position
321 551 : GUIMEVehicle::getVisualPosition(bool s2, const double offset) const {
322 551 : 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 547 : const MSLane* first = getEdge()->getLanes()[0];
328 547 : PositionVector shp = first->getShape(s2);
329 1093 : shp.move2side(SUMO_const_laneWidth * (MSGlobals::gLefthand ? -1 : 1));
330 547 : return shp.positionAtOffset((getPositionOnLane() + offset) * first->getLengthGeometryFactor(s2));
331 547 : }
332 4 : return MEVehicle::getPosition(offset);
333 : }
334 :
335 : bool
336 0 : GUIMEVehicle::isSelected() const {
337 0 : return gSelected.isSelected(GLO_VEHICLE, getGlID());
338 : }
339 :
340 : /****************************************************************************/
|