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