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