Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2012-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 Vehicle.cpp
15 : /// @author Jakob Erdmann
16 : /// @author Mirko Barthauer
17 : /// @date 15.03.2017
18 : ///
19 : // C++ Vehicle API
20 : /****************************************************************************/
21 : #include <config.h>
22 :
23 : #include <foreign/tcpip/storage.h>
24 : #include <utils/geom/GeomHelper.h>
25 : #include <utils/common/MsgHandler.h>
26 : #include <utils/common/StringTokenizer.h>
27 : #include <utils/common/StringUtils.h>
28 : #include <utils/gui/globjects/GUIGlObjectTypes.h>
29 : #include <utils/emissions/PollutantsInterface.h>
30 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
31 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
32 : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
33 : #include <microsim/devices/MSDevice.h>
34 : #include <microsim/MSEdgeWeightsStorage.h>
35 : #include <microsim/MSStop.h>
36 : #include <microsim/MSVehicle.h>
37 : #include <microsim/MSVehicleControl.h>
38 : #include <microsim/MSVehicleTransfer.h>
39 : #include <microsim/MSVehicleType.h>
40 : #include <microsim/MSInsertionControl.h>
41 : #include <microsim/MSNet.h>
42 : #include <microsim/MSEdge.h>
43 : #include <microsim/MSLane.h>
44 : #include <microsim/MSParkingArea.h>
45 : #include <microsim/MSJunctionLogic.h>
46 : #include <microsim/devices/MSDevice_Taxi.h>
47 : #include <microsim/devices/MSDispatch_TraCI.h>
48 : #include <mesosim/MEVehicle.h>
49 : #include <libsumo/TraCIDefs.h>
50 : #include <libsumo/TraCIConstants.h>
51 : #include "Helper.h"
52 : #include "Route.h"
53 : #include "Polygon.h"
54 : #include "Vehicle.h"
55 :
56 : #define CALL_MICRO_FUN(veh, fun, mesoResult) ((dynamic_cast<MSVehicle*>(veh) == nullptr ? (mesoResult) : dynamic_cast<MSVehicle*>(veh)->fun))
57 : #define CALL_MESO_FUN(veh, fun, microResult) ((dynamic_cast<MEVehicle*>(veh) == nullptr ? (microResult) : dynamic_cast<MEVehicle*>(veh)->fun))
58 :
59 : // ===========================================================================
60 : // debug defines
61 : // ===========================================================================
62 : //#define DEBUG_NEIGHBORS
63 : //#define DEBUG_DYNAMIC_SHAPES
64 : //#define DEBUG_MOVEXY
65 : #define DEBUG_COND (veh->isSelected())
66 :
67 :
68 :
69 : namespace libsumo {
70 : // ===========================================================================
71 : // static member initializations
72 : // ===========================================================================
73 : SubscriptionResults Vehicle::mySubscriptionResults;
74 : ContextSubscriptionResults Vehicle::myContextSubscriptionResults;
75 :
76 :
77 : // ===========================================================================
78 : // static member definitions
79 : // ===========================================================================
80 : bool
81 7499199 : Vehicle::isVisible(const SUMOVehicle* veh) {
82 7499199 : return veh->isOnRoad() || veh->isParking() || veh->wasRemoteControlled();
83 : }
84 :
85 :
86 : bool
87 22245 : Vehicle::isOnInit(const std::string& vehID) {
88 22245 : SUMOVehicle* sumoVehicle = MSNet::getInstance()->getVehicleControl().getVehicle(vehID);
89 22245 : return sumoVehicle == nullptr || sumoVehicle->getLane() == nullptr;
90 : }
91 :
92 :
93 : std::vector<std::string>
94 157524 : Vehicle::getIDList() {
95 : std::vector<std::string> ids;
96 157524 : MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
97 1709104 : for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
98 1551582 : if (isVisible((*i).second)) {
99 1531682 : ids.push_back((*i).first);
100 : }
101 : }
102 157522 : return ids;
103 2 : }
104 :
105 : int
106 139 : Vehicle::getIDCount() {
107 139 : return (int)getIDList().size();
108 : }
109 :
110 :
111 : double
112 175795 : Vehicle::getSpeed(const std::string& vehID) {
113 175795 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
114 175748 : return isVisible(veh) ? veh->getSpeed() : INVALID_DOUBLE_VALUE;
115 : }
116 :
117 : double
118 82 : Vehicle::getLateralSpeed(const std::string& vehID) {
119 82 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
120 82 : return isVisible(veh) ? CALL_MICRO_FUN(veh, getLaneChangeModel().getSpeedLat(), 0) : INVALID_DOUBLE_VALUE;
121 : }
122 :
123 :
124 : double
125 4978 : Vehicle::getAcceleration(const std::string& vehID) {
126 4978 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
127 4978 : return isVisible(veh) ? CALL_MICRO_FUN(veh, getAcceleration(), 0) : INVALID_DOUBLE_VALUE;
128 : }
129 :
130 :
131 : double
132 4131 : Vehicle::getSpeedWithoutTraCI(const std::string& vehID) {
133 4131 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
134 4131 : return isVisible(veh) ? CALL_MICRO_FUN(veh, getSpeedWithoutTraciInfluence(), veh->getSpeed()) : INVALID_DOUBLE_VALUE;
135 : }
136 :
137 :
138 : TraCIPosition
139 1671508 : Vehicle::getPosition(const std::string& vehID, const bool includeZ) {
140 1671508 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
141 1671503 : if (isVisible(veh)) {
142 1671331 : return Helper::makeTraCIPosition(veh->getPosition(), includeZ);
143 : }
144 : return TraCIPosition();
145 : }
146 :
147 :
148 : TraCIPosition
149 798 : Vehicle::getPosition3D(const std::string& vehID) {
150 798 : return getPosition(vehID, true);
151 : }
152 :
153 :
154 : double
155 443 : Vehicle::getAngle(const std::string& vehID) {
156 443 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
157 443 : return isVisible(veh) ? GeomHelper::naviDegree(veh->getAngle()) : INVALID_DOUBLE_VALUE;
158 : }
159 :
160 :
161 : double
162 10 : Vehicle::getSlope(const std::string& vehID) {
163 10 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
164 10 : return (veh->isOnRoad() || veh->isParking()) ? veh->getSlope() : INVALID_DOUBLE_VALUE;
165 : }
166 :
167 :
168 : std::string
169 4089028 : Vehicle::getRoadID(const std::string& vehID) {
170 4089028 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
171 4089028 : return isVisible(veh) ? CALL_MICRO_FUN(veh, getLane()->getEdge().getID(), veh->getEdge()->getID()) : "";
172 : }
173 :
174 :
175 : std::string
176 38104 : Vehicle::getLaneID(const std::string& vehID) {
177 38104 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
178 38089 : return veh->isOnRoad() ? CALL_MICRO_FUN(veh, getLane()->getID(), "") : "";
179 : }
180 :
181 :
182 : int
183 32619 : Vehicle::getLaneIndex(const std::string& vehID) {
184 32619 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
185 32614 : if (veh->isOnRoad()) {
186 32555 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
187 32555 : if (microVeh != nullptr) {
188 32534 : return microVeh->getLane()->getIndex();
189 : } else {
190 21 : MEVehicle* mesoVeh = dynamic_cast<MEVehicle*>(veh);
191 21 : return mesoVeh->getQueIndex();
192 : }
193 : } else {
194 : return INVALID_INT_VALUE;
195 : }
196 : }
197 :
198 : std::string
199 90 : Vehicle::getSegmentID(const std::string& vehID) {
200 90 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
201 86 : return veh->isOnRoad() ? CALL_MESO_FUN(veh, getSegment()->getID(), "") : "";
202 : }
203 :
204 : int
205 86 : Vehicle::getSegmentIndex(const std::string& vehID) {
206 86 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
207 86 : return veh->isOnRoad() ? CALL_MESO_FUN(veh, getSegment()->getIndex(), INVALID_INT_VALUE) : INVALID_INT_VALUE;
208 : }
209 :
210 : std::string
211 20135 : Vehicle::getTypeID(const std::string& vehID) {
212 20135 : return Helper::getVehicleType(vehID).getID();
213 : }
214 :
215 :
216 : std::string
217 127 : Vehicle::getRouteID(const std::string& vehID) {
218 127 : return Helper::getVehicle(vehID)->getRoute().getID();
219 : }
220 :
221 :
222 : double
223 81 : Vehicle::getDeparture(const std::string& vehID) {
224 81 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
225 81 : return veh->hasDeparted() ? STEPS2TIME(veh->getDeparture()) : INVALID_DOUBLE_VALUE;
226 : }
227 :
228 :
229 : double
230 81 : Vehicle::getDepartDelay(const std::string& vehID) {
231 81 : return STEPS2TIME(Helper::getVehicle(vehID)->getDepartDelay());
232 : }
233 :
234 :
235 : int
236 3336 : Vehicle::getRouteIndex(const std::string& vehID) {
237 3336 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
238 3336 : return veh->hasDeparted() ? veh->getRoutePosition() : INVALID_INT_VALUE;
239 : }
240 :
241 :
242 : TraCIColor
243 675 : Vehicle::getColor(const std::string& vehID) {
244 675 : return Helper::makeTraCIColor(Helper::getVehicle(vehID)->getParameter().color);
245 : }
246 :
247 : double
248 4073348 : Vehicle::getLanePosition(const std::string& vehID) {
249 4073348 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
250 4073343 : return (veh->isOnRoad() || veh->isParking()) ? veh->getPositionOnLane() : INVALID_DOUBLE_VALUE;
251 : }
252 :
253 : double
254 3563 : Vehicle::getLateralLanePosition(const std::string& vehID) {
255 3563 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
256 3563 : return veh->isOnRoad() ? CALL_MICRO_FUN(veh, getLateralPositionOnLane(), 0) : INVALID_DOUBLE_VALUE;
257 : }
258 :
259 : double
260 443 : Vehicle::getCO2Emission(const std::string& vehID) {
261 443 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
262 443 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::CO2>() : INVALID_DOUBLE_VALUE;
263 : }
264 :
265 : double
266 83 : Vehicle::getCOEmission(const std::string& vehID) {
267 83 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
268 83 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::CO>() : INVALID_DOUBLE_VALUE;
269 : }
270 :
271 : double
272 83 : Vehicle::getHCEmission(const std::string& vehID) {
273 83 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
274 83 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::HC>() : INVALID_DOUBLE_VALUE;
275 : }
276 :
277 : double
278 83 : Vehicle::getPMxEmission(const std::string& vehID) {
279 83 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
280 83 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::PM_X>() : INVALID_DOUBLE_VALUE;
281 : }
282 :
283 : double
284 83 : Vehicle::getNOxEmission(const std::string& vehID) {
285 83 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
286 83 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::NO_X>() : INVALID_DOUBLE_VALUE;
287 : }
288 :
289 : double
290 433 : Vehicle::getFuelConsumption(const std::string& vehID) {
291 433 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
292 433 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::FUEL>() : INVALID_DOUBLE_VALUE;
293 : }
294 :
295 : double
296 83 : Vehicle::getNoiseEmission(const std::string& vehID) {
297 83 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
298 83 : return isVisible(veh) ? veh->getHarmonoise_NoiseEmissions() : INVALID_DOUBLE_VALUE;
299 : }
300 :
301 : double
302 171 : Vehicle::getElectricityConsumption(const std::string& vehID) {
303 171 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
304 171 : return isVisible(veh) ? veh->getEmissions<PollutantsInterface::ELEC>() : INVALID_DOUBLE_VALUE;
305 : }
306 :
307 : int
308 306 : Vehicle::getPersonNumber(const std::string& vehID) {
309 306 : return Helper::getVehicle(vehID)->getPersonNumber();
310 : }
311 :
312 : int
313 319 : Vehicle::getPersonCapacity(const std::string& vehID) {
314 319 : return Helper::getVehicleType(vehID).getPersonCapacity();
315 : }
316 :
317 :
318 : double
319 81 : Vehicle::getBoardingDuration(const std::string& vehID) {
320 81 : return STEPS2TIME(Helper::getVehicleType(vehID).getLoadingDuration(true));
321 : }
322 :
323 :
324 : std::vector<std::string>
325 186 : Vehicle::getPersonIDList(const std::string& vehID) {
326 186 : return Helper::getVehicle(vehID)->getPersonIDList();
327 : }
328 :
329 : std::pair<std::string, double>
330 39200 : Vehicle::getLeader(const std::string& vehID, double dist) {
331 39200 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
332 39200 : if (veh->isOnRoad()) {
333 39124 : std::pair<const MSVehicle* const, double> leaderInfo = veh->getLeader(dist);
334 39124 : const std::string leaderID = leaderInfo.first != nullptr ? leaderInfo.first->getID() : "";
335 39124 : double gap = leaderInfo.second;
336 : if (leaderInfo.first != nullptr
337 31038 : && leaderInfo.first->getLane() != nullptr
338 31038 : && leaderInfo.first->getLane()->isInternal()
339 156 : && veh->getLane() != nullptr
340 39280 : && (!veh->getLane()->isInternal()
341 6 : || (veh->getLane()->getLinkCont().front()->getIndex() != leaderInfo.first->getLane()->getLinkCont().front()->getIndex()))) {
342 : // leader is a linkLeader (see MSLink::getLeaderInfo)
343 : // avoid internal gap values which may be negative (or -inf)
344 : gap = MAX2(0.0, gap);
345 : }
346 : return std::make_pair(leaderID, gap);
347 : } else {
348 : return std::make_pair("", -1);
349 : }
350 : }
351 :
352 :
353 : std::pair<std::string, double>
354 294 : Vehicle::getFollower(const std::string& vehID, double dist) {
355 294 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
356 289 : if (veh->isOnRoad()) {
357 279 : std::pair<const MSVehicle* const, double> leaderInfo = veh->getFollower(dist);
358 : return std::make_pair(
359 558 : leaderInfo.first != nullptr ? leaderInfo.first->getID() : "",
360 : leaderInfo.second);
361 : } else {
362 : return std::make_pair("", -1);
363 : }
364 : }
365 :
366 :
367 : std::vector<TraCIJunctionFoe>
368 150 : Vehicle::getJunctionFoes(const std::string& vehID, double dist) {
369 : std::vector<TraCIJunctionFoe> result;
370 150 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
371 150 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
372 150 : if (veh == nullptr) {
373 60 : WRITE_WARNING("getJunctionFoes not applicable for meso");
374 120 : } else if (veh->isOnRoad()) {
375 120 : if (dist == 0) {
376 0 : dist = veh->getCarFollowModel().brakeGap(veh->getSpeed()) + veh->getVehicleType().getMinGap();
377 : }
378 : const std::vector<const MSLane*> internalLanes;
379 : // distance to the end of the lane
380 120 : double curDist = -veh->getPositionOnLane();
381 364 : for (const MSLane* lane : veh->getUpcomingLanesUntil(dist)) {
382 244 : curDist += lane->getLength();
383 244 : if (lane->isInternal()) {
384 116 : const MSLink* exitLink = lane->getLinkCont().front();
385 : int foeIndex = 0;
386 : const std::vector<MSLink::ConflictInfo>& conflicts = exitLink->getConflicts();
387 116 : const MSJunctionLogic* logic = exitLink->getJunction()->getLogic();
388 288 : for (const MSLane* foeLane : exitLink->getFoeLanes()) {
389 172 : const MSLink::ConflictInfo& ci = conflicts[foeIndex];
390 172 : if (ci.flag == MSLink::CONFLICT_NO_INTERSECTION) {
391 112 : continue;
392 : }
393 60 : const double distBehindCrossing = ci.lengthBehindCrossing;
394 60 : const MSLink* foeExitLink = foeLane->getLinkCont().front();
395 60 : const double distToCrossing = curDist - distBehindCrossing;
396 60 : const double foeDistBehindCrossing = ci.getFoeLengthBehindCrossing(foeExitLink);
397 240 : for (auto item : foeExitLink->getApproaching()) {
398 : const SUMOVehicle* foe = item.first;
399 : TraCIJunctionFoe jf;
400 : jf.foeId = foe->getID();
401 180 : jf.egoDist = distToCrossing;
402 : // approach information is from the start of the previous step
403 : // but the foe vehicle then moved within that steop
404 180 : const double prevFoeDist = SPEED2DIST(MSGlobals::gSemiImplicitEulerUpdate
405 : ? foe->getSpeed()
406 : : (foe->getSpeed() + foe->getPreviousSpeed()) / 2);
407 180 : jf.foeDist = item.second.dist - foeDistBehindCrossing - prevFoeDist;
408 180 : jf.egoExitDist = jf.egoDist + ci.conflictSize;
409 180 : jf.foeExitDist = jf.foeDist + ci.getFoeConflictSize(foeExitLink);
410 : jf.egoLane = lane->getID();
411 : jf.foeLane = foeLane->getID();
412 180 : jf.egoResponse = logic->getResponseFor(exitLink->getIndex()).test(foeExitLink->getIndex());
413 180 : jf.foeResponse = logic->getResponseFor(foeExitLink->getIndex()).test(exitLink->getIndex());
414 180 : result.push_back(jf);
415 180 : }
416 60 : foeIndex++;
417 : }
418 : }
419 120 : }
420 120 : }
421 150 : return result;
422 0 : }
423 :
424 :
425 : double
426 239 : Vehicle::getWaitingTime(const std::string& vehID) {
427 239 : return STEPS2TIME(Helper::getVehicle(vehID)->getWaitingTime());
428 : }
429 :
430 :
431 : double
432 117 : Vehicle::getAccumulatedWaitingTime(const std::string& vehID) {
433 117 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
434 117 : return CALL_MICRO_FUN(veh, getAccumulatedWaitingSeconds(), INVALID_DOUBLE_VALUE);
435 : }
436 :
437 :
438 : double
439 111 : Vehicle::getAdaptedTraveltime(const std::string& vehID, double time, const std::string& edgeID) {
440 111 : MSEdge* edge = Helper::getEdge(edgeID);
441 111 : double value = INVALID_DOUBLE_VALUE;
442 111 : Helper::getVehicle(vehID)->getWeightsStorage().retrieveExistingTravelTime(edge, time, value);
443 111 : return value;
444 : }
445 :
446 :
447 : double
448 107 : Vehicle::getEffort(const std::string& vehID, double time, const std::string& edgeID) {
449 107 : MSEdge* edge = Helper::getEdge(edgeID);
450 107 : double value = INVALID_DOUBLE_VALUE;
451 107 : Helper::getVehicle(vehID)->getWeightsStorage().retrieveExistingEffort(edge, time, value);
452 107 : return value;
453 : }
454 :
455 :
456 : bool
457 82 : Vehicle::isRouteValid(const std::string& vehID) {
458 : std::string msg;
459 164 : return Helper::getVehicle(vehID)->hasValidRoute(msg);
460 : }
461 :
462 :
463 : std::vector<std::string>
464 3598 : Vehicle::getRoute(const std::string& vehID) {
465 : std::vector<std::string> result;
466 3598 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
467 3598 : const MSRoute& r = veh->getRoute();
468 11887 : for (MSRouteIterator i = r.begin(); i != r.end(); ++i) {
469 8289 : result.push_back((*i)->getID());
470 : }
471 3598 : return result;
472 0 : }
473 :
474 :
475 : int
476 84 : Vehicle::getSignals(const std::string& vehID) {
477 84 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
478 84 : return CALL_MICRO_FUN(veh, getSignals(), MSVehicle::VEH_SIGNAL_NONE);
479 : }
480 :
481 :
482 : std::vector<TraCIBestLanesData>
483 86 : Vehicle::getBestLanes(const std::string& vehID) {
484 : std::vector<TraCIBestLanesData> result;
485 86 : MSVehicle* veh = dynamic_cast<MSVehicle*>(Helper::getVehicle(vehID));
486 86 : if (veh != nullptr && veh->isOnRoad()) {
487 98 : for (const MSVehicle::LaneQ& lq : veh->getBestLanes()) {
488 : TraCIBestLanesData bld;
489 61 : bld.laneID = lq.lane->getID();
490 61 : bld.length = lq.length;
491 61 : bld.occupation = lq.nextOccupation;
492 61 : bld.bestLaneOffset = lq.bestLaneOffset;
493 61 : bld.allowsContinuation = lq.allowsContinuation;
494 270 : for (const MSLane* const lane : lq.bestContinuations) {
495 209 : if (lane != nullptr) {
496 209 : bld.continuationLanes.push_back(lane->getID());
497 : }
498 : }
499 61 : result.emplace_back(bld);
500 : }
501 : }
502 86 : return result;
503 0 : }
504 :
505 :
506 : std::vector<TraCINextTLSData>
507 1329 : Vehicle::getNextTLS(const std::string& vehID) {
508 : std::vector<TraCINextTLSData> result;
509 1329 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
510 1323 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
511 1323 : if (veh != nullptr) {
512 : int view = 1;
513 1086 : double seen = veh->getEdge()->getLength() - veh->getPositionOnLane();
514 1086 : if (vehicle->isOnRoad()) {
515 1047 : const MSLane* lane = veh->getLane();
516 1047 : const std::vector<MSLane*>& bestLaneConts = veh->getBestLanesContinuation(lane);
517 1047 : seen = lane->getLength() - veh->getPositionOnLane();
518 1047 : std::vector<MSLink*>::const_iterator linkIt = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
519 2956 : while (!lane->isLinkEnd(linkIt)) {
520 1909 : if (!lane->getEdge().isInternal()) {
521 915 : if ((*linkIt)->isTLSControlled()) {
522 : TraCINextTLSData ntd;
523 670 : ntd.id = (*linkIt)->getTLLogic()->getID();
524 670 : ntd.tlIndex = (*linkIt)->getTLIndex();
525 670 : ntd.dist = seen;
526 670 : ntd.state = (char)(*linkIt)->getState();
527 670 : result.push_back(ntd);
528 : }
529 : }
530 1909 : lane = (*linkIt)->getViaLaneOrLane();
531 1909 : if (!lane->getEdge().isInternal()) {
532 966 : view++;
533 : }
534 1909 : seen += lane->getLength();
535 1909 : linkIt = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
536 : }
537 : }
538 : // consider edges beyond bestLanes
539 1086 : const int remainingEdges = (int)(veh->getRoute().end() - veh->getCurrentRouteEdge()) - view;
540 : //std::cout << SIMTIME << " remainingEdges=" << remainingEdges << " seen=" << seen << " view=" << view << " best=" << toString(bestLaneConts) << "\n";
541 2230 : for (int i = 0; i < remainingEdges; i++) {
542 1144 : const MSEdge* prev = *(veh->getCurrentRouteEdge() + view + i - 1);
543 1144 : const MSEdge* next = *(veh->getCurrentRouteEdge() + view + i);
544 1144 : const std::vector<MSLane*>* allowed = prev->allowedLanes(*next, veh->getVClass());
545 1144 : if (allowed != nullptr && allowed->size() != 0) {
546 1258 : for (const MSLink* const link : allowed->front()->getLinkCont()) {
547 1258 : if (&link->getLane()->getEdge() == next) {
548 1144 : if (link->isTLSControlled()) {
549 : TraCINextTLSData ntd;
550 : ntd.id = link->getTLLogic()->getID();
551 735 : ntd.tlIndex = link->getTLIndex();
552 735 : ntd.dist = seen;
553 735 : ntd.state = (char)link->getState();
554 735 : result.push_back(ntd);
555 : }
556 1144 : seen += next->getLength() + link->getInternalLengthsAfter();
557 1144 : break;
558 : }
559 : }
560 : } else {
561 : // invalid route, cannot determine nextTLS
562 : break;
563 : }
564 : }
565 :
566 : } else {
567 474 : WRITE_WARNING("getNextTLS not yet implemented for meso");
568 : }
569 1323 : return result;
570 6 : }
571 :
572 : std::vector<TraCINextStopData>
573 52 : Vehicle::getNextStops(const std::string& vehID) {
574 52 : return getStops(vehID, 0);
575 : }
576 :
577 : std::vector<libsumo::TraCIConnection>
578 4 : Vehicle::getNextLinks(const std::string& vehID) {
579 : std::vector<libsumo::TraCIConnection> result;
580 4 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
581 4 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
582 4 : if (!vehicle->isOnRoad()) {
583 : return result;
584 : }
585 4 : if (veh != nullptr) {
586 4 : const MSLane* lane = veh->getLane();
587 4 : const std::vector<MSLane*>& bestLaneConts = veh->getBestLanesContinuation(lane);
588 : int view = 1;
589 4 : const SUMOTime currTime = MSNet::getInstance()->getCurrentTimeStep();
590 4 : std::vector<MSLink*>::const_iterator linkIt = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
591 20 : while (!lane->isLinkEnd(linkIt)) {
592 16 : if (!lane->getEdge().isInternal()) {
593 8 : const MSLink* link = (*linkIt);
594 16 : const std::string approachedLane = link->getLane() != nullptr ? link->getLane()->getID() : "";
595 : const bool hasPrio = link->havePriority();
596 : const double speed = MIN2(lane->getSpeedLimit(), link->getLane()->getSpeedLimit());
597 8 : const bool isOpen = link->opened(currTime, speed, speed, veh->getLength(),
598 8 : veh->getImpatience(), veh->getVehicleType().getCarFollowModel().getMaxDecel(),
599 8 : veh->getWaitingTime(), veh->getLateralPositionOnLane(), nullptr, false, veh);
600 8 : const bool hasFoe = link->hasApproachingFoe(currTime, currTime, 0, SUMOVTypeParameter::getDefaultDecel());
601 16 : const std::string approachedInternal = link->getViaLane() != nullptr ? link->getViaLane()->getID() : "";
602 8 : const std::string state = SUMOXMLDefinitions::LinkStates.getString(link->getState());
603 8 : const std::string direction = SUMOXMLDefinitions::LinkDirections.getString(link->getDirection());
604 : const double length = link->getLength();
605 24 : result.push_back(TraCIConnection(approachedLane, hasPrio, isOpen, hasFoe, approachedInternal, state, direction, length));
606 : }
607 16 : lane = (*linkIt)->getViaLaneOrLane();
608 16 : if (!lane->getEdge().isInternal()) {
609 8 : view++;
610 : }
611 16 : linkIt = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
612 : }
613 : // consider edges beyond bestLanes
614 4 : const int remainingEdges = (int)(veh->getRoute().end() - veh->getCurrentRouteEdge()) - view;
615 4 : for (int i = 0; i < remainingEdges; i++) {
616 0 : const MSEdge* prev = *(veh->getCurrentRouteEdge() + view + i - 1);
617 0 : const MSEdge* next = *(veh->getCurrentRouteEdge() + view + i);
618 0 : const std::vector<MSLane*>* allowed = prev->allowedLanes(*next, veh->getVClass());
619 0 : if (allowed != nullptr && allowed->size() != 0) {
620 0 : for (const MSLink* const link : allowed->front()->getLinkCont()) {
621 0 : if (&link->getLane()->getEdge() == next) {
622 : const std::string approachedLane = link->getLane() != nullptr ? link->getLane()->getID() : "";
623 : const bool hasPrio = link->havePriority();
624 : const double speed = MIN2(lane->getSpeedLimit(), link->getLane()->getSpeedLimit());
625 0 : const bool isOpen = link->opened(currTime, speed, speed, veh->getLength(),
626 0 : veh->getImpatience(), veh->getVehicleType().getCarFollowModel().getMaxDecel(),
627 0 : veh->getWaitingTime(), veh->getLateralPositionOnLane(), nullptr, false, veh);
628 0 : const bool hasFoe = link->hasApproachingFoe(currTime, currTime, 0, SUMOVTypeParameter::getDefaultDecel());
629 0 : const std::string approachedInternal = link->getViaLane() != nullptr ? link->getViaLane()->getID() : "";
630 0 : const std::string state = SUMOXMLDefinitions::LinkStates.getString(link->getState());
631 0 : const std::string direction = SUMOXMLDefinitions::LinkDirections.getString(link->getDirection());
632 : const double length = link->getLength();
633 0 : result.push_back(TraCIConnection(approachedLane, hasPrio, isOpen, hasFoe, approachedInternal, state, direction, length));
634 : }
635 : }
636 : } else {
637 : // invalid route, cannot determine nextTLS
638 : break;
639 : }
640 : }
641 : } else {
642 0 : WRITE_WARNING("getNextLinks not yet implemented for meso");
643 : }
644 : return result;
645 0 : }
646 :
647 : std::vector<TraCINextStopData>
648 3400 : Vehicle::getStops(const std::string& vehID, int limit) {
649 : std::vector<TraCINextStopData> result;
650 3400 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
651 3398 : if (limit < 0) {
652 : // return past stops up to the given limit
653 : const std::vector<SUMOVehicleParameter::Stop>& pastStops = vehicle->getPastStops();
654 521 : const int n = (int)pastStops.size();
655 1502 : for (int i = MAX2(0, n + limit); i < n; i++) {
656 1962 : result.push_back(Helper::buildStopData(pastStops[i]));
657 : }
658 : } else {
659 9981 : for (const MSStop& stop : vehicle->getStops()) {
660 7666 : if (!stop.pars.collision) {
661 7666 : TraCINextStopData nsd = Helper::buildStopData(stop.pars);
662 7666 : nsd.duration = STEPS2TIME(stop.duration);
663 7666 : result.push_back(nsd);
664 7666 : if (limit > 0 && (int)result.size() >= limit) {
665 : break;
666 : }
667 7666 : }
668 : }
669 : }
670 3398 : return result;
671 2 : }
672 :
673 :
674 : int
675 1633 : Vehicle::getStopState(const std::string& vehID) {
676 1633 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
677 1633 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
678 1633 : if (veh == nullptr) {
679 411 : WRITE_WARNING("getStopState not yet implemented for meso");
680 411 : return 0;
681 : }
682 : int result = 0;
683 1222 : if (veh->isStopped()) {
684 159 : const MSStop& stop = veh->getNextStop();
685 159 : result = stop.getStateFlagsOld();
686 : }
687 : return result;
688 : }
689 :
690 :
691 : double
692 629 : Vehicle::getDistance(const std::string& vehID) {
693 629 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
694 624 : if (veh->hasDeparted()) {
695 579 : return veh->getOdometer();
696 : } else {
697 : return INVALID_DOUBLE_VALUE;
698 : }
699 : }
700 :
701 :
702 : double
703 3116 : Vehicle::getDrivingDistance(const std::string& vehID, const std::string& edgeID, double pos, int laneIndex) {
704 3116 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
705 3116 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
706 3116 : if (veh->isOnRoad()) {
707 3071 : const MSLane* lane = microVeh != nullptr ? veh->getLane() : veh->getEdge()->getLanes()[0];
708 6142 : double distance = veh->getRoute().getDistanceBetween(veh->getPositionOnLane(), pos,
709 3071 : lane, Helper::getLaneChecking(edgeID, laneIndex, pos), veh->getRoutePosition());
710 3071 : if (distance == std::numeric_limits<double>::max()) {
711 : return INVALID_DOUBLE_VALUE;
712 : }
713 : return distance;
714 : } else {
715 : return INVALID_DOUBLE_VALUE;
716 : }
717 : }
718 :
719 :
720 : double
721 84 : Vehicle::getDrivingDistance2D(const std::string& vehID, double x, double y) {
722 84 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
723 84 : if (veh == nullptr) {
724 : return INVALID_DOUBLE_VALUE;
725 : }
726 84 : if (veh->isOnRoad()) {
727 39 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
728 39 : const MSLane* lane = microVeh != nullptr ? veh->getLane() : veh->getEdge()->getLanes()[0];
729 39 : std::pair<MSLane*, double> roadPos = Helper::convertCartesianToRoadMap(Position(x, y), veh->getVehicleType().getVehicleClass());
730 78 : double distance = veh->getRoute().getDistanceBetween(veh->getPositionOnLane(), roadPos.second,
731 39 : lane, roadPos.first, veh->getRoutePosition());
732 39 : if (distance == std::numeric_limits<double>::max()) {
733 : return INVALID_DOUBLE_VALUE;
734 : }
735 28 : return distance;
736 : } else {
737 : return INVALID_DOUBLE_VALUE;
738 : }
739 : }
740 :
741 :
742 : double
743 81 : Vehicle::getAllowedSpeed(const std::string& vehID) {
744 81 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
745 81 : return veh->isOnRoad() ? CALL_MICRO_FUN(veh, getLane()->getVehicleMaxSpeed(veh), veh->getEdge()->getVehicleMaxSpeed(veh)) : INVALID_DOUBLE_VALUE;
746 : }
747 :
748 :
749 : double
750 185 : Vehicle::getSpeedFactor(const std::string& vehID) {
751 185 : return Helper::getVehicle(vehID)->getChosenSpeedFactor();
752 : }
753 :
754 :
755 : int
756 63 : Vehicle::getSpeedMode(const std::string& vehID) {
757 63 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
758 63 : return CALL_MICRO_FUN(veh, getInfluencer().getSpeedMode(), INVALID_INT_VALUE);
759 : }
760 :
761 :
762 : int
763 170 : Vehicle::getLaneChangeMode(const std::string& vehID) {
764 170 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
765 170 : return CALL_MICRO_FUN(veh, getInfluencer().getLaneChangeMode(), INVALID_INT_VALUE);
766 : }
767 :
768 :
769 : int
770 179 : Vehicle::getRoutingMode(const std::string& vehID) {
771 179 : return Helper::getVehicle(vehID)->getRoutingMode();
772 : }
773 :
774 :
775 : std::string
776 82 : Vehicle::getLine(const std::string& vehID) {
777 82 : return Helper::getVehicle(vehID)->getParameter().line;
778 : }
779 :
780 :
781 : std::vector<std::string>
782 82 : Vehicle::getVia(const std::string& vehID) {
783 82 : return Helper::getVehicle(vehID)->getParameter().via;
784 : }
785 :
786 :
787 : std::pair<int, int>
788 16363 : Vehicle::getLaneChangeState(const std::string& vehID, int direction) {
789 16363 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
790 16363 : auto undefined = std::make_pair((int)LCA_UNKNOWN, (int)LCA_UNKNOWN);
791 16363 : return veh->isOnRoad() ? CALL_MICRO_FUN(veh, getLaneChangeModel().getSavedState(direction), undefined) : undefined;
792 : }
793 :
794 :
795 : std::string
796 49403 : Vehicle::getParameter(const std::string& vehID, const std::string& key) {
797 49403 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
798 : std::string error;
799 49403 : std::string result = veh->getPrefixedParameter(key, error);
800 49403 : if (error != "") {
801 154 : throw TraCIException(error);
802 : }
803 49326 : return result;
804 : }
805 :
806 :
807 48 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(Vehicle)
808 :
809 :
810 : std::vector<std::pair<std::string, double> >
811 4280 : Vehicle::getNeighbors(const std::string& vehID, const int mode) {
812 4280 : int dir = (1 & mode) != 0 ? -1 : 1;
813 4280 : bool queryLeaders = (2 & mode) != 0;
814 4280 : bool blockersOnly = (4 & mode) != 0;
815 4280 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
816 4280 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
817 : std::vector<std::pair<std::string, double> > result;
818 4280 : if (veh == nullptr) {
819 : return result;
820 : }
821 : #ifdef DEBUG_NEIGHBORS
822 : if (DEBUG_COND) {
823 : std::cout << "getNeighbors() for veh '" << vehID << "': dir=" << dir
824 : << ", queryLeaders=" << queryLeaders
825 : << ", blockersOnly=" << blockersOnly << std::endl;
826 : }
827 : #endif
828 4280 : if (veh->getLaneChangeModel().isOpposite()) {
829 : // getParallelLane works relative to lane forward direction
830 120 : dir *= -1;
831 : }
832 :
833 4280 : MSLane* targetLane = veh->getLane()->getParallelLane(dir);
834 4280 : if (targetLane == nullptr) {
835 : return result;
836 : }
837 : // need to recompute leaders and followers (#8119)
838 3700 : const bool opposite = &veh->getLane()->getEdge() != &targetLane->getEdge();
839 3700 : MSLeaderDistanceInfo neighbors(targetLane->getWidth(), nullptr, 0.);
840 3700 : if (queryLeaders) {
841 1850 : if (opposite) {
842 290 : double pos = targetLane->getOppositePos(veh->getPositionOnLane());
843 290 : neighbors = targetLane->getFollowersOnConsecutive(veh, pos, true);
844 : } else {
845 1560 : targetLane->addLeaders(veh, veh->getPositionOnLane(), neighbors);
846 : }
847 : } else {
848 1850 : if (opposite) {
849 290 : double pos = targetLane->getOppositePos(veh->getPositionOnLane());
850 290 : targetLane->addLeaders(veh, pos, neighbors);
851 290 : neighbors.fixOppositeGaps(true);
852 : } else {
853 1560 : neighbors = targetLane->getFollowersOnConsecutive(veh, veh->getBackPositionOnLane(), true);
854 : }
855 : }
856 3700 : if (blockersOnly) {
857 : // filter out vehicles that aren't blocking
858 1850 : MSLeaderDistanceInfo blockers(targetLane->getWidth(), nullptr, 0.);
859 6040 : for (int i = 0; i < neighbors.numSublanes(); i++) {
860 4190 : CLeaderDist n = neighbors[i];
861 4190 : if (n.first != nullptr) {
862 : const MSVehicle* follower = veh;
863 : const MSVehicle* leader = n.first;
864 2665 : if (!queryLeaders) {
865 : std::swap(follower, leader);
866 : }
867 5330 : const double secureGap = (follower->getCarFollowModel().getSecureGap(
868 2665 : follower, leader, follower->getSpeed(), leader->getSpeed(), leader->getCarFollowModel().getMaxDecel())
869 2665 : * follower->getLaneChangeModel().getSafetyFactor());
870 2665 : if (n.second < secureGap) {
871 1170 : blockers.addLeader(n.first, n.second, 0, i);
872 : }
873 : }
874 : }
875 1850 : neighbors = blockers;
876 1850 : }
877 :
878 3700 : if (neighbors.hasVehicles()) {
879 6575 : for (int i = 0; i < neighbors.numSublanes(); i++) {
880 4720 : CLeaderDist n = neighbors[i];
881 4720 : if (n.first != nullptr &&
882 : // avoid duplicates
883 1995 : (result.size() == 0 || result.back().first != n.first->getID())) {
884 2360 : result.push_back(std::make_pair(n.first->getID(), n.second));
885 : }
886 : }
887 : }
888 : return result;
889 3700 : }
890 :
891 :
892 : double
893 534 : Vehicle::getFollowSpeed(const std::string& vehID, double speed, double gap, double leaderSpeed, double leaderMaxDecel, const std::string& leaderID) {
894 534 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
895 534 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
896 534 : if (veh == nullptr) {
897 0 : WRITE_ERROR("getFollowSpeed not applicable for meso");
898 0 : return INVALID_DOUBLE_VALUE;
899 : }
900 534 : MSVehicle* leader = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(leaderID));
901 534 : return veh->getCarFollowModel().followSpeed(veh, speed, gap, leaderSpeed, leaderMaxDecel, leader, MSCFModel::CalcReason::FUTURE);
902 : }
903 :
904 :
905 : double
906 9 : Vehicle::getSecureGap(const std::string& vehID, double speed, double leaderSpeed, double leaderMaxDecel, const std::string& leaderID) {
907 9 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
908 9 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
909 9 : if (veh == nullptr) {
910 0 : WRITE_ERROR("getSecureGap not applicable for meso");
911 0 : return INVALID_DOUBLE_VALUE;
912 : }
913 9 : MSVehicle* leader = dynamic_cast<MSVehicle*>(MSNet::getInstance()->getVehicleControl().getVehicle(leaderID));
914 9 : return veh->getCarFollowModel().getSecureGap(veh, leader, speed, leaderSpeed, leaderMaxDecel);
915 : }
916 :
917 :
918 : double
919 9 : Vehicle::getStopSpeed(const std::string& vehID, const double speed, double gap) {
920 9 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
921 9 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
922 9 : if (veh == nullptr) {
923 0 : WRITE_ERROR("getStopSpeed not applicable for meso");
924 0 : return INVALID_DOUBLE_VALUE;
925 : }
926 9 : return veh->getCarFollowModel().stopSpeed(veh, speed, gap, MSCFModel::CalcReason::FUTURE);
927 : }
928 :
929 : double
930 1858 : Vehicle::getStopDelay(const std::string& vehID) {
931 1858 : return Helper::getVehicle(vehID)->getStopDelay();
932 : }
933 :
934 :
935 : double
936 108 : Vehicle::getImpatience(const std::string& vehID) {
937 108 : return Helper::getVehicle(vehID)->getImpatience();
938 : }
939 :
940 :
941 : double
942 1857 : Vehicle::getStopArrivalDelay(const std::string& vehID) {
943 1857 : double result = Helper::getVehicle(vehID)->getStopArrivalDelay();
944 1857 : if (result == INVALID_DOUBLE) {
945 : return INVALID_DOUBLE_VALUE;
946 : } else {
947 1368 : return result;
948 : }
949 : }
950 :
951 : double
952 81 : Vehicle::getTimeLoss(const std::string& vehID) {
953 81 : return Helper::getVehicle(vehID)->getTimeLossSeconds();
954 : }
955 :
956 : std::vector<std::string>
957 9403 : Vehicle::getTaxiFleet(int taxiState) {
958 : std::vector<std::string> result;
959 22678 : for (MSDevice_Taxi* taxi : MSDevice_Taxi::getFleet()) {
960 13275 : if (taxi->getHolder().hasDeparted()) {
961 : if (taxiState == -1
962 9436 : || (taxiState == 0 && taxi->getState() == 0)
963 19918 : || (taxiState != 0 && (taxi->getState() & taxiState) == taxiState)) {
964 5989 : result.push_back(taxi->getHolder().getID());
965 : }
966 : }
967 : }
968 9403 : return result;
969 0 : }
970 :
971 : std::vector<std::string>
972 177 : Vehicle::getLoadedIDList() {
973 : std::vector<std::string> ids;
974 177 : MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
975 508 : for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
976 331 : ids.push_back(i->first);
977 : }
978 177 : return ids;
979 0 : }
980 :
981 : std::vector<std::string>
982 132 : Vehicle::getTeleportingIDList() {
983 : std::vector<std::string> ids;
984 132 : MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
985 438 : for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
986 306 : SUMOVehicle* veh = i->second;
987 306 : if (veh->hasDeparted() && !isVisible(veh)) {
988 60 : ids.push_back(veh->getID());
989 : }
990 : }
991 132 : return ids;
992 0 : }
993 :
994 : std::string
995 76 : Vehicle::getEmissionClass(const std::string& vehID) {
996 76 : return PollutantsInterface::getName(Helper::getVehicleType(vehID).getEmissionClass());
997 : }
998 :
999 : std::string
1000 36 : Vehicle::getShapeClass(const std::string& vehID) {
1001 36 : return getVehicleShapeName(Helper::getVehicleType(vehID).getGuiShape());
1002 : }
1003 :
1004 :
1005 : double
1006 38 : Vehicle::getLength(const std::string& vehID) {
1007 38 : return Helper::getVehicleType(vehID).getLength();
1008 : }
1009 :
1010 :
1011 : double
1012 38 : Vehicle::getAccel(const std::string& vehID) {
1013 38 : return Helper::getVehicleType(vehID).getCarFollowModel().getMaxAccel();
1014 : }
1015 :
1016 :
1017 : double
1018 225 : Vehicle::getDecel(const std::string& vehID) {
1019 225 : return Helper::getVehicleType(vehID).getCarFollowModel().getMaxDecel();
1020 : }
1021 :
1022 :
1023 42 : double Vehicle::getEmergencyDecel(const std::string& vehID) {
1024 42 : return Helper::getVehicleType(vehID).getCarFollowModel().getEmergencyDecel();
1025 : }
1026 :
1027 :
1028 38 : double Vehicle::getApparentDecel(const std::string& vehID) {
1029 38 : return Helper::getVehicleType(vehID).getCarFollowModel().getApparentDecel();
1030 : }
1031 :
1032 :
1033 38 : double Vehicle::getActionStepLength(const std::string& vehID) {
1034 38 : return Helper::getVehicleType(vehID).getActionStepLengthSecs();
1035 : }
1036 :
1037 :
1038 81 : double Vehicle::getLastActionTime(const std::string& vehID) {
1039 81 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
1040 81 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
1041 81 : if (microVeh != nullptr) {
1042 72 : return STEPS2TIME(microVeh->getLastActionTime());
1043 : } else {
1044 9 : MEVehicle* mesoVeh = dynamic_cast<MEVehicle*>(veh);
1045 9 : return STEPS2TIME(mesoVeh->getEventTime());
1046 : }
1047 : }
1048 :
1049 :
1050 : double
1051 38 : Vehicle::getTau(const std::string& vehID) {
1052 38 : return Helper::getVehicleType(vehID).getCarFollowModel().getHeadwayTime();
1053 : }
1054 :
1055 :
1056 : double
1057 40 : Vehicle::getImperfection(const std::string& vehID) {
1058 40 : return Helper::getVehicleType(vehID).getCarFollowModel().getImperfection();
1059 : }
1060 :
1061 :
1062 : double
1063 36 : Vehicle::getSpeedDeviation(const std::string& vehID) {
1064 36 : return Helper::getVehicleType(vehID).getSpeedFactor().getParameter()[1];
1065 : }
1066 :
1067 :
1068 : std::string
1069 36 : Vehicle::getVehicleClass(const std::string& vehID) {
1070 36 : return toString(Helper::getVehicleType(vehID).getVehicleClass());
1071 : }
1072 :
1073 :
1074 : double
1075 92 : Vehicle::getMinGap(const std::string& vehID) {
1076 92 : return Helper::getVehicleType(vehID).getMinGap();
1077 : }
1078 :
1079 :
1080 : double
1081 81 : Vehicle::getMinGapLat(const std::string& vehID) {
1082 : try {
1083 117 : return StringUtils::toDouble(getParameter(vehID, "laneChangeModel.minGapLat"));
1084 45 : } catch (const TraCIException&) {
1085 : // legacy behavior
1086 45 : return Helper::getVehicleType(vehID).getMinGapLat();
1087 45 : }
1088 : }
1089 :
1090 :
1091 : double
1092 38 : Vehicle::getMaxSpeed(const std::string& vehID) {
1093 38 : return Helper::getVehicleType(vehID).getMaxSpeed();
1094 : }
1095 :
1096 :
1097 : double
1098 36 : Vehicle::getMaxSpeedLat(const std::string& vehID) {
1099 36 : return Helper::getVehicleType(vehID).getMaxSpeedLat();
1100 : }
1101 :
1102 :
1103 : std::string
1104 36 : Vehicle::getLateralAlignment(const std::string& vehID) {
1105 36 : return toString(Helper::getVehicleType(vehID).getPreferredLateralAlignment());
1106 : }
1107 :
1108 :
1109 : double
1110 38 : Vehicle::getWidth(const std::string& vehID) {
1111 38 : return Helper::getVehicleType(vehID).getWidth();
1112 : }
1113 :
1114 :
1115 : double
1116 36 : Vehicle::getHeight(const std::string& vehID) {
1117 36 : return Helper::getVehicleType(vehID).getHeight();
1118 : }
1119 :
1120 :
1121 : double
1122 44 : Vehicle::getMass(const std::string& vehID) {
1123 44 : return Helper::getVehicleType(vehID).getMass();
1124 : }
1125 :
1126 :
1127 : void
1128 45100 : Vehicle::setStop(const std::string& vehID,
1129 : const std::string& edgeID,
1130 : double pos,
1131 : int laneIndex,
1132 : double duration,
1133 : int flags,
1134 : double startPos,
1135 : double until) {
1136 45100 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1137 : SUMOVehicleParameter::Stop stopPars = Helper::buildStopParameters(edgeID,
1138 45098 : pos, laneIndex, startPos, flags, duration, until);
1139 : std::string error;
1140 45111 : if (!vehicle->addTraciStop(stopPars, error)) {
1141 26 : throw TraCIException(error);
1142 : }
1143 45098 : }
1144 :
1145 :
1146 : void
1147 213 : Vehicle::replaceStop(const std::string& vehID,
1148 : int nextStopIndex,
1149 : const std::string& edgeID,
1150 : double pos,
1151 : int laneIndex,
1152 : double duration,
1153 : int flags,
1154 : double startPos,
1155 : double until,
1156 : int teleport) {
1157 213 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1158 : std::string error;
1159 213 : if (edgeID == "") {
1160 : // only remove stop
1161 86 : const bool ok = vehicle->abortNextStop(nextStopIndex);
1162 86 : if (teleport != 0) {
1163 117 : if (!vehicle->rerouteBetweenStops(nextStopIndex, "traci:replaceStop", (teleport & 1), error)) {
1164 0 : throw TraCIException("Stop replacement failed for vehicle '" + vehID + "' (" + error + ").");
1165 : }
1166 : } else {
1167 36 : MSVehicle* msVeh = dynamic_cast<MSVehicle*>(vehicle);
1168 36 : if (msVeh->getLane() != nullptr) {
1169 28 : msVeh->updateBestLanes(true);
1170 : }
1171 : }
1172 86 : if (!ok) {
1173 0 : throw TraCIException("Stop replacement failed for vehicle '" + vehID + "' (invalid nextStopIndex).");
1174 : }
1175 : } else {
1176 : SUMOVehicleParameter::Stop stopPars = Helper::buildStopParameters(edgeID,
1177 127 : pos, laneIndex, startPos, flags, duration, until);
1178 :
1179 127 : if (!vehicle->replaceStop(nextStopIndex, stopPars, "traci:replaceStop", teleport != 0, error)) {
1180 34 : throw TraCIException("Stop replacement failed for vehicle '" + vehID + "' (" + error + ").");
1181 : }
1182 127 : }
1183 196 : }
1184 :
1185 :
1186 : void
1187 138 : Vehicle::insertStop(const std::string& vehID,
1188 : int nextStopIndex,
1189 : const std::string& edgeID,
1190 : double pos,
1191 : int laneIndex,
1192 : double duration,
1193 : int flags,
1194 : double startPos,
1195 : double until,
1196 : int teleport) {
1197 138 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1198 : SUMOVehicleParameter::Stop stopPars = Helper::buildStopParameters(edgeID,
1199 138 : pos, laneIndex, startPos, flags, duration, until);
1200 :
1201 : std::string error;
1202 149 : if (!vehicle->insertStop(nextStopIndex, stopPars, "traci:insertStop", teleport != 0, error)) {
1203 32 : throw TraCIException("Stop insertion failed for vehicle '" + vehID + "' (" + error + ").");
1204 : }
1205 133 : }
1206 :
1207 :
1208 : std::string
1209 433 : Vehicle::getStopParameter(const std::string& vehID, int nextStopIndex, const std::string& param, bool customParam) {
1210 433 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1211 : try {
1212 433 : if (nextStopIndex >= (int)vehicle->getStops().size() || (nextStopIndex < 0 && -nextStopIndex > (int)vehicle->getPastStops().size())) {
1213 0 : throw ProcessError("Invalid stop index " + toString(nextStopIndex)
1214 0 : + " (has " + toString(vehicle->getPastStops().size()) + " past stops and " + toString(vehicle->getStops().size()) + " remaining stops)");
1215 :
1216 : }
1217 : const SUMOVehicleParameter::Stop& pars = (nextStopIndex >= 0
1218 433 : ? vehicle->getStop(nextStopIndex).pars
1219 198 : : vehicle->getPastStops()[vehicle->getPastStops().size() + nextStopIndex]);
1220 433 : if (customParam) {
1221 : // custom user parameter
1222 20 : return pars.getParameter(param, "");
1223 : }
1224 :
1225 423 : if (param == toString(SUMO_ATTR_EDGE)) {
1226 : return pars.edge;
1227 404 : } else if (param == toString(SUMO_ATTR_LANE)) {
1228 72 : return toString(SUMOXMLDefinitions::getIndexFromLane(pars.lane));
1229 760 : } else if (param == toString(SUMO_ATTR_BUS_STOP)
1230 760 : || param == toString(SUMO_ATTR_TRAIN_STOP)) {
1231 : return pars.busstop;
1232 380 : } else if (param == toString(SUMO_ATTR_CONTAINER_STOP)) {
1233 : return pars.containerstop;
1234 380 : } else if (param == toString(SUMO_ATTR_CHARGING_STATION)) {
1235 : return pars.chargingStation;
1236 380 : } else if (param == toString(SUMO_ATTR_PARKING_AREA)) {
1237 : return pars.parkingarea;
1238 380 : } else if (param == toString(SUMO_ATTR_STARTPOS)) {
1239 19 : return toString(pars.startPos);
1240 361 : } else if (param == toString(SUMO_ATTR_ENDPOS)) {
1241 19 : return toString(pars.endPos);
1242 342 : } else if (param == toString(SUMO_ATTR_POSITION_LAT)) {
1243 19 : return toString(pars.posLat == INVALID_DOUBLE ? INVALID_DOUBLE_VALUE : pars.posLat);
1244 323 : } else if (param == toString(SUMO_ATTR_ARRIVAL)) {
1245 19 : return pars.arrival < 0 ? "-1" : time2string(pars.arrival);
1246 304 : } else if (param == toString(SUMO_ATTR_DURATION)) {
1247 19 : return pars.duration < 0 ? "-1" : time2string(pars.duration);
1248 285 : } else if (param == toString(SUMO_ATTR_UNTIL)) {
1249 19 : return pars.until < 0 ? "-1" : time2string(pars.until);
1250 266 : } else if (param == toString(SUMO_ATTR_EXTENSION)) {
1251 19 : return pars.extension < 0 ? "-1" : time2string(pars.extension);
1252 247 : } else if (param == toString(SUMO_ATTR_INDEX)) {
1253 19 : return toString(nextStopIndex + vehicle->getPastStops().size());
1254 228 : } else if (param == toString(SUMO_ATTR_PARKING)) {
1255 19 : return toString(pars.parking);
1256 209 : } else if (param == toString(SUMO_ATTR_TRIGGERED)) {
1257 19 : return joinToString(pars.getTriggers(), " ");
1258 190 : } else if (param == toString(SUMO_ATTR_EXPECTED)) {
1259 19 : return joinToString(pars.awaitedPersons, " ");
1260 171 : } else if (param == toString(SUMO_ATTR_EXPECTED_CONTAINERS)) {
1261 0 : return joinToString(pars.awaitedContainers, " ");
1262 171 : } else if (param == toString(SUMO_ATTR_PERMITTED)) {
1263 19 : return joinToString(pars.permitted, " ");
1264 152 : } else if (param == toString(SUMO_ATTR_ACTTYPE)) {
1265 : return pars.actType;
1266 133 : } else if (param == toString(SUMO_ATTR_TRIP_ID)) {
1267 : return pars.tripId;
1268 114 : } else if (param == toString(SUMO_ATTR_SPLIT)) {
1269 : return pars.split;
1270 95 : } else if (param == toString(SUMO_ATTR_JOIN)) {
1271 : return pars.join;
1272 76 : } else if (param == toString(SUMO_ATTR_LINE)) {
1273 : return pars.line;
1274 57 : } else if (param == toString(SUMO_ATTR_SPEED)) {
1275 19 : return toString(pars.speed);
1276 38 : } else if (param == toString(SUMO_ATTR_STARTED)) {
1277 19 : return pars.started < 0 ? "-1" : time2string(pars.started);
1278 19 : } else if (param == toString(SUMO_ATTR_ENDED)) {
1279 19 : return pars.ended < 0 ? "-1" : time2string(pars.ended);
1280 0 : } else if (param == toString(SUMO_ATTR_ONDEMAND)) {
1281 0 : return toString(pars.onDemand);
1282 : } else {
1283 0 : throw ProcessError(TLF("Unsupported parameter '%'", param));
1284 : }
1285 0 : } catch (ProcessError& e) {
1286 0 : throw TraCIException("Could not get stop parameter for vehicle '" + vehID + "' (" + e.what() + ")");
1287 0 : }
1288 : }
1289 :
1290 :
1291 :
1292 : void
1293 171 : Vehicle::setStopParameter(const std::string& vehID, int nextStopIndex,
1294 : const std::string& param, const std::string& value,
1295 : bool customParam) {
1296 171 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1297 : try {
1298 171 : MSStop& stop = vehicle->getStop(nextStopIndex);
1299 171 : SUMOVehicleParameter::Stop& pars = const_cast<SUMOVehicleParameter::Stop&>(stop.pars);
1300 171 : if (customParam) {
1301 10 : pars.setParameter(param, value);
1302 10 : return;
1303 : }
1304 : std::string error;
1305 322 : if (param == toString(SUMO_ATTR_EDGE)
1306 317 : || param == toString(SUMO_ATTR_BUS_STOP)
1307 312 : || param == toString(SUMO_ATTR_TRAIN_STOP)
1308 312 : || param == toString(SUMO_ATTR_CONTAINER_STOP)
1309 312 : || param == toString(SUMO_ATTR_CHARGING_STATION)
1310 312 : || param == toString(SUMO_ATTR_PARKING_AREA)
1311 468 : || param == toString(SUMO_ATTR_LANE)
1312 : ) {
1313 15 : int laneIndex = stop.lane->getIndex();
1314 15 : int flags = pars.getFlags() & 3;
1315 : std::string edgeOrStopID = value;
1316 15 : if (param == toString(SUMO_ATTR_LANE)) {
1317 5 : laneIndex = StringUtils::toInt(value);
1318 5 : edgeOrStopID = pars.edge;
1319 20 : } else if (param == toString(SUMO_ATTR_BUS_STOP)
1320 15 : || param == toString(SUMO_ATTR_TRAIN_STOP)) {
1321 5 : flags |= 8;
1322 5 : } else if (param == toString(SUMO_ATTR_CONTAINER_STOP)) {
1323 0 : flags |= 16;
1324 5 : } else if (param == toString(SUMO_ATTR_CHARGING_STATION)) {
1325 0 : flags |= 32;
1326 5 : } else if (param == toString(SUMO_ATTR_PARKING_AREA)) {
1327 0 : flags |= 64;
1328 : }
1329 : // special case: replace stop
1330 15 : replaceStop(vehID, nextStopIndex, edgeOrStopID, pars.endPos, laneIndex, STEPS2TIME(pars.duration),
1331 15 : flags, pars.startPos, STEPS2TIME(pars.until), 0);
1332 :
1333 146 : } else if (param == toString(SUMO_ATTR_STARTPOS)) {
1334 5 : pars.startPos = StringUtils::toDouble(value);
1335 5 : pars.parametersSet |= STOP_START_SET;
1336 141 : } else if (param == toString(SUMO_ATTR_ENDPOS)) {
1337 5 : pars.endPos = StringUtils::toDouble(value);
1338 5 : pars.parametersSet |= STOP_END_SET;
1339 136 : } else if (param == toString(SUMO_ATTR_POSITION_LAT)) {
1340 5 : pars.posLat = StringUtils::toDouble(value);
1341 5 : pars.parametersSet |= STOP_POSLAT_SET;
1342 131 : } else if (param == toString(SUMO_ATTR_ARRIVAL)) {
1343 5 : pars.arrival = string2time(value);
1344 5 : pars.parametersSet |= STOP_ARRIVAL_SET;
1345 126 : } else if (param == toString(SUMO_ATTR_DURATION)) {
1346 10 : pars.duration = string2time(value);
1347 10 : pars.parametersSet |= STOP_DURATION_SET;
1348 : // also update dynamic value
1349 10 : stop.initPars(pars);
1350 116 : } else if (param == toString(SUMO_ATTR_UNTIL)) {
1351 5 : pars.until = string2time(value);
1352 5 : pars.parametersSet |= STOP_UNTIL_SET;
1353 111 : } else if (param == toString(SUMO_ATTR_EXTENSION)) {
1354 10 : pars.extension = string2time(value);
1355 10 : pars.parametersSet |= STOP_EXTENSION_SET;
1356 101 : } else if (param == toString(SUMO_ATTR_INDEX)) {
1357 0 : throw TraCIException("Changing stop index is not supported");
1358 101 : } else if (param == toString(SUMO_ATTR_PARKING)) {
1359 5 : pars.parking = SUMOVehicleParameter::parseParkingType(value);
1360 5 : pars.parametersSet |= STOP_PARKING_SET;
1361 96 : } else if (param == toString(SUMO_ATTR_TRIGGERED)) {
1362 10 : if (pars.speed > 0 && value != "") {
1363 0 : throw ProcessError(TLF("Waypoint (speed = %) at index % does not support triggers", pars.speed, nextStopIndex));
1364 : }
1365 10 : SUMOVehicleParameter::parseStopTriggers(StringTokenizer(value).getVector(), false, pars);
1366 10 : pars.parametersSet |= STOP_TRIGGER_SET;
1367 : // also update dynamic value
1368 10 : stop.initPars(pars);
1369 86 : } else if (param == toString(SUMO_ATTR_EXPECTED)) {
1370 28 : pars.awaitedPersons = StringTokenizer(value).getSet();
1371 14 : pars.parametersSet |= STOP_EXPECTED_SET;
1372 : // also update dynamic value
1373 14 : stop.initPars(pars);
1374 72 : } else if (param == toString(SUMO_ATTR_EXPECTED_CONTAINERS)) {
1375 0 : pars.awaitedContainers = StringTokenizer(value).getSet();
1376 0 : pars.parametersSet |= STOP_EXPECTED_CONTAINERS_SET;
1377 : // also update dynamic value
1378 0 : stop.initPars(pars);
1379 72 : } else if (param == toString(SUMO_ATTR_PERMITTED)) {
1380 10 : pars.permitted = StringTokenizer(value).getSet();
1381 5 : pars.parametersSet |= STOP_PERMITTED_SET;
1382 67 : } else if (param == toString(SUMO_ATTR_ACTTYPE)) {
1383 5 : pars.actType = value;
1384 62 : } else if (param == toString(SUMO_ATTR_TRIP_ID)) {
1385 5 : pars.tripId = value;
1386 5 : pars.parametersSet |= STOP_TRIP_ID_SET;
1387 57 : } else if (param == toString(SUMO_ATTR_SPLIT)) {
1388 5 : pars.split = value;
1389 5 : pars.parametersSet |= STOP_SPLIT_SET;
1390 52 : } else if (param == toString(SUMO_ATTR_JOIN)) {
1391 5 : pars.join = value;
1392 5 : pars.parametersSet |= STOP_JOIN_SET;
1393 : // also update dynamic value
1394 5 : stop.initPars(pars);
1395 47 : } else if (param == toString(SUMO_ATTR_LINE)) {
1396 5 : pars.line = value;
1397 5 : pars.parametersSet |= STOP_LINE_SET;
1398 42 : } else if (param == toString(SUMO_ATTR_SPEED)) {
1399 10 : const double speed = StringUtils::toDouble(value);
1400 15 : if (speed > 0 && pars.getTriggers().size() > 0) {
1401 10 : throw ProcessError(TLF("Triggered stop at index % cannot be changed into a waypoint by setting speed to %", nextStopIndex, speed));
1402 : }
1403 5 : pars.speed = speed;
1404 5 : pars.parametersSet |= STOP_SPEED_SET;
1405 32 : } else if (param == toString(SUMO_ATTR_STARTED)) {
1406 5 : pars.started = string2time(value);
1407 5 : pars.parametersSet |= STOP_STARTED_SET;
1408 27 : } else if (param == toString(SUMO_ATTR_ENDED)) {
1409 5 : pars.ended = string2time(value);
1410 5 : pars.parametersSet |= STOP_ENDED_SET;
1411 22 : } else if (param == toString(SUMO_ATTR_ONDEMAND)) {
1412 5 : pars.onDemand = StringUtils::toBool(value);
1413 5 : pars.parametersSet |= STOP_ONDEMAND_SET;
1414 22 : } else if (param == toString(SUMO_ATTR_JUMP)) {
1415 17 : pars.jump = string2time(value);
1416 17 : pars.parametersSet |= STOP_JUMP_SET;
1417 : } else {
1418 0 : throw ProcessError(TLF("Unsupported parameter '%'", param));
1419 : }
1420 5 : } catch (ProcessError& e) {
1421 10 : throw TraCIException("Could not set stop parameter for vehicle '" + vehID + "' (" + e.what() + ")");
1422 5 : }
1423 : }
1424 :
1425 :
1426 : void
1427 15 : Vehicle::rerouteParkingArea(const std::string& vehID, const std::string& parkingAreaID) {
1428 15 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1429 15 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1430 15 : if (veh == nullptr) {
1431 0 : WRITE_WARNING("rerouteParkingArea not yet implemented for meso");
1432 0 : return;
1433 : }
1434 : std::string error;
1435 : // Forward command to vehicle
1436 15 : if (!veh->rerouteParkingArea(parkingAreaID, error)) {
1437 0 : throw TraCIException(error);
1438 : }
1439 : }
1440 :
1441 : void
1442 7 : Vehicle::resume(const std::string& vehID) {
1443 7 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1444 7 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1445 7 : if (veh == nullptr) {
1446 1 : WRITE_WARNING("resume not yet implemented for meso");
1447 1 : return;
1448 : }
1449 6 : if (!veh->hasStops()) {
1450 0 : throw TraCIException("Failed to resume vehicle '" + veh->getID() + "', it has no stops.");
1451 : }
1452 6 : if (!veh->resumeFromStopping()) {
1453 0 : MSStop& sto = veh->getNextStop();
1454 0 : std::ostringstream strs;
1455 0 : strs << "reached: " << sto.reached;
1456 0 : strs << ", duration:" << sto.duration;
1457 0 : strs << ", edge:" << (*sto.edge)->getID();
1458 0 : strs << ", startPos: " << sto.pars.startPos;
1459 : std::string posStr = strs.str();
1460 0 : throw TraCIException("Failed to resume from stopping for vehicle '" + veh->getID() + "', " + posStr);
1461 0 : }
1462 : }
1463 :
1464 :
1465 : void
1466 21869 : Vehicle::changeTarget(const std::string& vehID, const std::string& edgeID) {
1467 21869 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
1468 21869 : const MSEdge* destEdge = MSEdge::dictionary(edgeID);
1469 21869 : const bool onInit = isOnInit(vehID);
1470 21869 : if (destEdge == nullptr) {
1471 2 : throw TraCIException("Destination edge '" + edgeID + "' is not known.");
1472 : }
1473 : // change the final edge of the route and reroute
1474 : try {
1475 21868 : const bool success = veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), "traci:changeTarget",
1476 : veh->getRouterTT(), onInit, false, false, destEdge);
1477 21868 : if (!success) {
1478 20 : throw TraCIException("ChangeTarget failed for vehicle '" + veh->getID() + "', destination edge '" + edgeID + "' unreachable.");
1479 : }
1480 0 : } catch (ProcessError& e) {
1481 0 : throw TraCIException(e.what());
1482 0 : }
1483 21858 : }
1484 :
1485 :
1486 : void
1487 7571 : Vehicle::changeLane(const std::string& vehID, int laneIndex, double duration) {
1488 : try {
1489 7571 : checkTimeBounds(duration);
1490 0 : } catch (ProcessError&) {
1491 0 : throw TraCIException("Duration parameter exceeds the time value range.");
1492 0 : }
1493 7571 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1494 7571 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1495 7571 : if (veh == nullptr) {
1496 0 : WRITE_ERROR("changeLane not applicable for meso");
1497 0 : return;
1498 : }
1499 :
1500 : std::vector<std::pair<SUMOTime, int> > laneTimeLine;
1501 7571 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), laneIndex));
1502 7571 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(duration), laneIndex));
1503 7571 : veh->getInfluencer().setLaneTimeLine(laneTimeLine);
1504 7571 : }
1505 :
1506 : void
1507 273 : Vehicle::changeLaneRelative(const std::string& vehID, int indexOffset, double duration) {
1508 : try {
1509 273 : checkTimeBounds(duration);
1510 0 : } catch (ProcessError&) {
1511 0 : throw TraCIException("Duration parameter exceeds the time value range.");
1512 0 : }
1513 273 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1514 273 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1515 273 : if (veh == nullptr) {
1516 0 : WRITE_ERROR("changeLaneRelative not applicable for meso");
1517 0 : return;
1518 : }
1519 :
1520 : std::vector<std::pair<SUMOTime, int> > laneTimeLine;
1521 273 : int laneIndex = veh->getLaneIndex() + indexOffset;
1522 273 : if (laneIndex < 0 && !veh->getLaneChangeModel().isOpposite()) {
1523 20 : if (veh->getLaneIndex() == -1) {
1524 0 : WRITE_WARNINGF(TL("Ignoring changeLaneRelative for vehicle '%' that isn't on the road"), vehID);
1525 : } else {
1526 60 : WRITE_WARNINGF(TL("Ignoring indexOffset % for vehicle '%' on laneIndex %."), indexOffset, vehID, veh->getLaneIndex());
1527 : }
1528 : } else {
1529 253 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), laneIndex));
1530 253 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(duration), laneIndex));
1531 253 : veh->getInfluencer().setLaneTimeLine(laneTimeLine);
1532 : }
1533 273 : }
1534 :
1535 :
1536 : void
1537 337 : Vehicle::changeSublane(const std::string& vehID, double latDist) {
1538 337 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1539 337 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1540 337 : if (veh == nullptr) {
1541 1 : WRITE_ERROR("changeSublane not applicable for meso");
1542 1 : return;
1543 : }
1544 :
1545 336 : veh->getInfluencer().setSublaneChange(latDist);
1546 : }
1547 :
1548 :
1549 : void
1550 22911 : Vehicle::add(const std::string& vehID,
1551 : const std::string& routeID,
1552 : const std::string& typeID,
1553 : const std::string& depart,
1554 : const std::string& departLane,
1555 : const std::string& departPos,
1556 : const std::string& departSpeed,
1557 : const std::string& arrivalLane,
1558 : const std::string& arrivalPos,
1559 : const std::string& arrivalSpeed,
1560 : const std::string& fromTaz,
1561 : const std::string& toTaz,
1562 : const std::string& line,
1563 : int /*personCapacity*/,
1564 : int personNumber) {
1565 22911 : SUMOVehicle* veh = MSNet::getInstance()->getVehicleControl().getVehicle(vehID);
1566 22911 : if (veh != nullptr) {
1567 2 : throw TraCIException("The vehicle '" + vehID + "' to add already exists.");
1568 : }
1569 :
1570 22910 : SUMOVehicleParameter vehicleParams;
1571 : vehicleParams.id = vehID;
1572 22910 : MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
1573 22910 : if (!vehicleType) {
1574 4 : throw TraCIException("Invalid type '" + typeID + "' for vehicle '" + vehID + "'.");
1575 : }
1576 22908 : if (typeID != "DEFAULT_VEHTYPE") {
1577 : vehicleParams.vtypeid = typeID;
1578 21841 : vehicleParams.parametersSet |= VEHPARS_VTYPE_SET;
1579 : }
1580 22908 : if (SUMOVehicleParserHelper::isInternalRouteID(routeID)) {
1581 0 : WRITE_WARNINGF(TL("Internal routes receive an ID starting with '!' and must not be referenced in other vehicle or flow definitions. Please remove all references to route '%' in case it is internal."), routeID);
1582 : }
1583 22908 : ConstMSRoutePtr route = MSRoute::dictionary(routeID);
1584 22908 : if (!route) {
1585 45 : if (routeID == "") {
1586 : // assume, route was intentionally left blank because the caller
1587 : // intends to control the vehicle remotely
1588 : SUMOVehicleClass vclass = vehicleType->getVehicleClass();
1589 43 : const std::string dummyRouteID = "DUMMY_ROUTE_" + SumoVehicleClassStrings.getString(vclass);
1590 86 : route = MSRoute::dictionary(dummyRouteID);
1591 43 : if (route == nullptr) {
1592 4585 : for (MSEdge* e : MSEdge::getAllEdges()) {
1593 4585 : if (e->getFunction() == SumoXMLEdgeFunc::NORMAL && (e->getPermissions() & vclass) == vclass) {
1594 : std::vector<std::string> edges;
1595 43 : edges.push_back(e->getID());
1596 43 : libsumo::Route::add(dummyRouteID, edges);
1597 : break;
1598 43 : }
1599 : }
1600 : }
1601 86 : route = MSRoute::dictionary(dummyRouteID);
1602 43 : if (!route) {
1603 0 : throw TraCIException("Could not build dummy route for vehicle class: '" + SumoVehicleClassStrings.getString(vehicleType->getVehicleClass()) + "'");
1604 : }
1605 : } else {
1606 4 : throw TraCIException("Invalid route '" + routeID + "' for vehicle '" + vehID + "'.");
1607 : }
1608 : }
1609 : // check if the route implies a trip
1610 22906 : if (route->getEdges().size() == 2) {
1611 22439 : const MSEdgeVector& succ = route->getEdges().front()->getSuccessors();
1612 22439 : if (std::find(succ.begin(), succ.end(), route->getEdges().back()) == succ.end()) {
1613 55 : vehicleParams.parametersSet |= VEHPARS_FORCE_REROUTE;
1614 : }
1615 : }
1616 22906 : if (fromTaz != "" || toTaz != "") {
1617 15 : vehicleParams.parametersSet |= VEHPARS_FORCE_REROUTE;
1618 : }
1619 : std::string error;
1620 45812 : if (!SUMOVehicleParameter::parseDepart(depart, "vehicle", vehID, vehicleParams.depart, vehicleParams.departProcedure, error)) {
1621 0 : throw TraCIException(error);
1622 : }
1623 22906 : if (vehicleParams.departProcedure == DepartDefinition::GIVEN && vehicleParams.depart < MSNet::getInstance()->getCurrentTimeStep()) {
1624 9 : vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
1625 27 : WRITE_WARNINGF(TL("Departure time for vehicle '%' is in the past; using current time instead."), vehID);
1626 22897 : } else if (vehicleParams.departProcedure == DepartDefinition::NOW) {
1627 22854 : vehicleParams.depart = MSNet::getInstance()->getCurrentTimeStep();
1628 : }
1629 45812 : if (!SUMOVehicleParameter::parseDepartLane(departLane, "vehicle", vehID, vehicleParams.departLane, vehicleParams.departLaneProcedure, error)) {
1630 10 : throw TraCIException(error);
1631 : }
1632 45802 : if (!SUMOVehicleParameter::parseDepartPos(departPos, "vehicle", vehID, vehicleParams.departPos, vehicleParams.departPosProcedure, error)) {
1633 0 : throw TraCIException(error);
1634 : }
1635 45802 : if (!SUMOVehicleParameter::parseDepartSpeed(departSpeed, "vehicle", vehID, vehicleParams.departSpeed, vehicleParams.departSpeedProcedure, error)) {
1636 0 : throw TraCIException(error);
1637 : }
1638 45802 : if (!SUMOVehicleParameter::parseArrivalLane(arrivalLane, "vehicle", vehID, vehicleParams.arrivalLane, vehicleParams.arrivalLaneProcedure, error)) {
1639 0 : throw TraCIException(error);
1640 : }
1641 45802 : if (!SUMOVehicleParameter::parseArrivalPos(arrivalPos, "vehicle", vehID, vehicleParams.arrivalPos, vehicleParams.arrivalPosProcedure, error)) {
1642 0 : throw TraCIException(error);
1643 : }
1644 45824 : if (!SUMOVehicleParameter::parseArrivalSpeed(arrivalSpeed, "vehicle", vehID, vehicleParams.arrivalSpeed, vehicleParams.arrivalSpeedProcedure, error)) {
1645 0 : throw TraCIException(error);
1646 : }
1647 : // mark non-default attributes
1648 22901 : if (departLane != "first") {
1649 21873 : vehicleParams.parametersSet |= VEHPARS_DEPARTLANE_SET;
1650 : }
1651 22901 : if (departPos != "base") {
1652 22071 : vehicleParams.parametersSet |= VEHPARS_DEPARTPOS_SET;
1653 : }
1654 22901 : if (departSpeed != "0") {
1655 21829 : vehicleParams.parametersSet |= VEHPARS_DEPARTSPEED_SET;
1656 : }
1657 22901 : if (arrivalLane != "current") {
1658 15 : vehicleParams.parametersSet |= VEHPARS_ARRIVALLANE_SET;
1659 : }
1660 22901 : if (arrivalPos != "max") {
1661 10 : vehicleParams.parametersSet |= VEHPARS_ARRIVALPOS_SET;
1662 : }
1663 22901 : if (arrivalSpeed != "current") {
1664 5 : vehicleParams.parametersSet |= VEHPARS_ARRIVALSPEED_SET;
1665 : }
1666 22901 : if (fromTaz != "") {
1667 10 : vehicleParams.parametersSet |= VEHPARS_FROM_TAZ_SET;
1668 : }
1669 22901 : if (toTaz != "") {
1670 10 : vehicleParams.parametersSet |= VEHPARS_TO_TAZ_SET;
1671 : }
1672 22901 : if (line != "") {
1673 18 : vehicleParams.parametersSet |= VEHPARS_LINE_SET;
1674 : }
1675 22901 : if (personNumber != 0) {
1676 0 : vehicleParams.parametersSet |= VEHPARS_PERSON_NUMBER_SET;
1677 : }
1678 : // build vehicle
1679 : vehicleParams.fromTaz = fromTaz;
1680 : vehicleParams.toTaz = toTaz;
1681 : vehicleParams.line = line;
1682 : //vehicleParams.personCapacity = personCapacity;
1683 22901 : vehicleParams.personNumber = personNumber;
1684 :
1685 22901 : SUMOVehicleParameter* params = new SUMOVehicleParameter(vehicleParams);
1686 : SUMOVehicle* vehicle = nullptr;
1687 : try {
1688 22918 : vehicle = MSNet::getInstance()->getVehicleControl().buildVehicle(params, route, vehicleType, true, MSVehicleControl::VehicleDefinitionSource::LIBSUMO);
1689 22901 : if (fromTaz == "" && !route->getEdges().front()->validateDepartSpeed(*vehicle)) {
1690 5 : MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle, true);
1691 10 : throw TraCIException("Departure speed for vehicle '" + vehID + "' is too high for the departure edge '" + route->getEdges().front()->getID() + "'.");
1692 : }
1693 : std::string msg;
1694 22896 : if (vehicle->getRouteValidity(true, true, &msg) != MSBaseVehicle::ROUTE_VALID) {
1695 5 : MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle, true);
1696 10 : throw TraCIException("Vehicle '" + vehID + "' has no valid route (" + msg + "). ");
1697 : }
1698 22884 : MSNet::getInstance()->getVehicleControl().addVehicle(vehicleParams.id, vehicle);
1699 22884 : if (vehicleParams.departProcedure != DepartDefinition::TRIGGERED && vehicleParams.departProcedure != DepartDefinition::CONTAINER_TRIGGERED) {
1700 22863 : MSNet::getInstance()->getInsertionControl().add(vehicle);
1701 : }
1702 17 : } catch (ProcessError& e) {
1703 7 : if (vehicle != nullptr) {
1704 7 : MSNet::getInstance()->getVehicleControl().deleteVehicle(vehicle, true);
1705 : }
1706 14 : throw TraCIException(e.what());
1707 7 : }
1708 22910 : }
1709 :
1710 :
1711 : void
1712 7792 : Vehicle::moveToXY(const std::string& vehID, const std::string& edgeID, const int laneIndex,
1713 : const double x, const double y, double angle, const int keepRoute, double matchThreshold) {
1714 7792 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1715 7792 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1716 7792 : if (veh == nullptr) {
1717 5 : WRITE_WARNING("moveToXY not yet implemented for meso");
1718 5 : return;
1719 : }
1720 7787 : const bool doKeepRoute = (keepRoute & 1) != 0 && veh->getID() != "VTD_EGO";
1721 7787 : const bool mayLeaveNetwork = (keepRoute & 2) != 0;
1722 7787 : const bool ignorePermissions = (keepRoute & 4) != 0;
1723 7787 : const bool setLateralPos = (MSGlobals::gLateralResolution > 0 || mayLeaveNetwork);
1724 7787 : SUMOVehicleClass vClass = ignorePermissions ? SVC_IGNORING : veh->getVClass();
1725 : // process
1726 15574 : const std::string origID = edgeID + "_" + toString(laneIndex);
1727 : // @todo add an interpretation layer for OSM derived origID values (without lane index)
1728 : Position pos(x, y);
1729 : #ifdef DEBUG_MOVEXY
1730 : const double origAngle = angle;
1731 : #endif
1732 : // angle must be in [0,360] because it will be compared against those returned by naviDegree()
1733 : // angle set to INVALID_DOUBLE_VALUE is ignored in the evaluated and later set to the angle of the matched lane
1734 7787 : if (angle != INVALID_DOUBLE_VALUE) {
1735 2823 : while (angle >= 360.) {
1736 0 : angle -= 360.;
1737 : }
1738 2828 : while (angle < 0.) {
1739 5 : angle += 360.;
1740 : }
1741 : }
1742 :
1743 : #ifdef DEBUG_MOVEXY
1744 : std::cout << std::endl << SIMTIME << " moveToXY veh=" << veh->getID() << " vehPos=" << veh->getPosition()
1745 : << " lane=" << Named::getIDSecure(veh->getLane()) << " lanePos=" << vehicle->getPositionOnLane() << std::endl;
1746 : std::cout << " wantedPos=" << pos << " origID=" << origID << " laneIndex=" << laneIndex << " origAngle=" << origAngle << " angle=" << angle << " keepRoute=" << keepRoute << std::endl;
1747 : #endif
1748 :
1749 : ConstMSEdgeVector edges;
1750 7787 : MSLane* lane = nullptr;
1751 : double lanePos;
1752 : double lanePosLat = 0;
1753 7787 : double bestDistance = std::numeric_limits<double>::max();
1754 7787 : int routeOffset = 0;
1755 : bool found;
1756 7787 : double maxRouteDistance = matchThreshold;
1757 : /* EGO vehicle is known to have a fixed route. @todo make this into a parameter of the TraCI call */
1758 7787 : if (doKeepRoute) {
1759 : // case a): vehicle is on its earlier route
1760 : // we additionally assume it is moving forward (SUMO-limit);
1761 : // note that the route ("edges") is not changed in this case
1762 :
1763 5135 : found = Helper::moveToXYMap_matchingRoutePosition(pos, origID,
1764 5135 : veh->getRoute().getEdges(), veh->getRoutePosition(),
1765 : vClass, setLateralPos,
1766 : bestDistance, &lane, lanePos, routeOffset);
1767 : // @note silenty ignoring mapping failure
1768 : } else {
1769 2652 : const double speed = pos.distanceTo2D(veh->getPosition()); // !!!veh->getSpeed();
1770 2652 : found = Helper::moveToXYMap(pos, maxRouteDistance, mayLeaveNetwork, origID, angle,
1771 2652 : speed, veh->getRoute().getEdges(), veh->getRoutePosition(), veh->getLane(), veh->getPositionOnLane(), veh->isOnRoad(),
1772 : vClass, setLateralPos,
1773 : bestDistance, &lane, lanePos, routeOffset, edges);
1774 : }
1775 7787 : if ((found && bestDistance <= maxRouteDistance) || mayLeaveNetwork) {
1776 : // optionally compute lateral offset
1777 7780 : pos.setz(veh->getPosition().z());
1778 7780 : if (found && setLateralPos) {
1779 5110 : const double perpDist = lane->getShape().distance2D(pos, false);
1780 5110 : if (perpDist != GeomHelper::INVALID_OFFSET) {
1781 : lanePosLat = perpDist;
1782 5110 : if (!mayLeaveNetwork) {
1783 57 : lanePosLat = MIN2(lanePosLat, 0.5 * (lane->getWidth() + veh->getVehicleType().getWidth() - MSGlobals::gLateralResolution));
1784 : }
1785 : // figure out whether the offset is to the left or to the right
1786 5110 : PositionVector tmp = lane->getShape();
1787 : try {
1788 5110 : tmp.move2side(-lanePosLat); // moved to left
1789 0 : } catch (ProcessError&) {
1790 0 : WRITE_WARNINGF(TL("Could not determine position on lane '%' at lateral position %."), lane->getID(), toString(-lanePosLat));
1791 0 : }
1792 : //std::cout << " lane=" << lane->getID() << " posLat=" << lanePosLat << " shape=" << lane->getShape() << " tmp=" << tmp << " tmpDist=" << tmp.distance2D(pos) << "\n";
1793 5110 : if (tmp.distance2D(pos) > perpDist) {
1794 : lanePosLat = -lanePosLat;
1795 : }
1796 5110 : }
1797 5110 : pos.setz(lane->geometryPositionAtOffset(lanePos).z());
1798 : }
1799 7780 : if (found && !mayLeaveNetwork && MSGlobals::gLateralResolution < 0) {
1800 : // mapped position may differ from pos
1801 2536 : pos = lane->geometryPositionAtOffset(lanePos, -lanePosLat);
1802 : }
1803 : assert((found && lane != 0) || (!found && lane == 0));
1804 : assert(!std::isnan(lanePos));
1805 7780 : if (angle == INVALID_DOUBLE_VALUE) {
1806 4959 : if (lane != nullptr) {
1807 4819 : angle = GeomHelper::naviDegree(lane->getShape().rotationAtOffset(lanePos));
1808 : } else {
1809 : // compute angle outside road network from old and new position
1810 140 : angle = GeomHelper::naviDegree(veh->getPosition().angleTo2D(pos));
1811 : }
1812 : }
1813 : // use the best we have
1814 : #ifdef DEBUG_MOVEXY
1815 : std::cout << SIMTIME << " veh=" << vehID + " moveToXYResult lane='" << Named::getIDSecure(lane) << "' lanePos=" << lanePos << " lanePosLat=" << lanePosLat << "\n";
1816 : #endif
1817 7780 : Helper::setRemoteControlled(veh, pos, lane, lanePos, lanePosLat, angle, routeOffset, edges, MSNet::getInstance()->getCurrentTimeStep());
1818 7780 : if (!veh->isOnRoad()) {
1819 195 : MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh);
1820 : }
1821 : } else {
1822 7 : if (lane == nullptr) {
1823 3 : throw TraCIException("Could not map vehicle '" + vehID + "', no road found within " + toString(maxRouteDistance) + "m.");
1824 : } else {
1825 18 : throw TraCIException("Could not map vehicle '" + vehID + "', distance to road is " + toString(bestDistance) + ".");
1826 : }
1827 : }
1828 7787 : }
1829 :
1830 : void
1831 53 : Vehicle::slowDown(const std::string& vehID, double speed, double duration) {
1832 : try {
1833 53 : checkTimeBounds(duration);
1834 0 : } catch (ProcessError&) {
1835 0 : throw TraCIException("Duration parameter exceeds the time value range.");
1836 0 : }
1837 53 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1838 53 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1839 53 : if (veh == nullptr) {
1840 6 : WRITE_ERROR("slowDown not applicable for meso");
1841 6 : return;
1842 : }
1843 :
1844 : std::vector<std::pair<SUMOTime, double> > speedTimeLine;
1845 47 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), veh->getSpeed()));
1846 47 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(duration), speed));
1847 47 : veh->getInfluencer().setSpeedTimeLine(speedTimeLine);
1848 47 : }
1849 :
1850 : void
1851 60 : Vehicle::openGap(const std::string& vehID, double newTimeHeadway, double newSpaceHeadway, double duration, double changeRate, double maxDecel, const std::string& referenceVehID) {
1852 : try {
1853 60 : checkTimeBounds(duration);
1854 0 : } catch (ProcessError&) {
1855 0 : throw TraCIException("Duration parameter exceeds the time value range.");
1856 0 : }
1857 60 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1858 60 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1859 60 : if (veh == nullptr) {
1860 0 : WRITE_ERROR("openGap not applicable for meso");
1861 0 : return;
1862 : }
1863 :
1864 : MSVehicle* refVeh = nullptr;
1865 60 : if (referenceVehID != "") {
1866 13 : refVeh = dynamic_cast<MSVehicle*>(Helper::getVehicle(referenceVehID));
1867 : }
1868 60 : const double originalTau = veh->getVehicleType().getCarFollowModel().getHeadwayTime();
1869 60 : if (newTimeHeadway == -1) {
1870 : newTimeHeadway = originalTau;
1871 : }
1872 60 : if (originalTau > newTimeHeadway) {
1873 4 : WRITE_WARNING("Ignoring openGap(). New time headway must not be smaller than the original.");
1874 4 : return;
1875 : }
1876 56 : veh->getInfluencer().activateGapController(originalTau, newTimeHeadway, newSpaceHeadway, duration, changeRate, maxDecel, refVeh);
1877 : }
1878 :
1879 : void
1880 8 : Vehicle::deactivateGapControl(const std::string& vehID) {
1881 8 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1882 8 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1883 8 : if (veh == nullptr) {
1884 0 : WRITE_ERROR("deactivateGapControl not applicable for meso");
1885 0 : return;
1886 : }
1887 :
1888 8 : if (veh->hasInfluencer()) {
1889 8 : veh->getInfluencer().deactivateGapController();
1890 : }
1891 : }
1892 :
1893 : void
1894 0 : Vehicle::requestToC(const std::string& vehID, double leadTime) {
1895 0 : setParameter(vehID, "device.toc.requestToC", toString(leadTime));
1896 0 : }
1897 :
1898 : void
1899 5720 : Vehicle::setSpeed(const std::string& vehID, double speed) {
1900 5720 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1901 5719 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1902 5719 : if (veh == nullptr) {
1903 6 : WRITE_WARNING("setSpeed not yet implemented for meso");
1904 6 : return;
1905 : }
1906 :
1907 : std::vector<std::pair<SUMOTime, double> > speedTimeLine;
1908 5713 : if (speed >= 0) {
1909 5678 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), speed));
1910 5678 : speedTimeLine.push_back(std::make_pair(SUMOTime_MAX - DELTA_T, speed));
1911 : }
1912 5713 : veh->getInfluencer().setSpeedTimeLine(speedTimeLine);
1913 5713 : }
1914 :
1915 : void
1916 12 : Vehicle::setAcceleration(const std::string& vehID, double acceleration, double duration) {
1917 : try {
1918 12 : checkTimeBounds(duration);
1919 0 : } catch (ProcessError&) {
1920 0 : throw TraCIException("Duration parameter exceeds the time value range.");
1921 0 : }
1922 12 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1923 12 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1924 12 : if (veh == nullptr) {
1925 3 : WRITE_WARNING("setAcceleration not yet implemented for meso");
1926 3 : return;
1927 : }
1928 :
1929 12 : double targetSpeed = std::max(veh->getSpeed() + acceleration * duration, 0.0);
1930 : std::vector<std::pair<SUMOTime, double>> speedTimeLine;
1931 9 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), veh->getSpeed()));
1932 9 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + TIME2STEPS(duration), targetSpeed));
1933 9 : veh->getInfluencer().setSpeedTimeLine(speedTimeLine);
1934 9 : }
1935 :
1936 : void
1937 243 : Vehicle::setPreviousSpeed(const std::string& vehID, double prevSpeed, double prevAcceleration) {
1938 243 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1939 243 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1940 243 : if (veh == nullptr) {
1941 2 : WRITE_WARNING("setPreviousSpeed not yet implemented for meso");
1942 2 : return;
1943 : }
1944 241 : if (prevAcceleration == INVALID_DOUBLE_VALUE) {
1945 : prevAcceleration = std::numeric_limits<double>::min();
1946 : }
1947 241 : veh->setPreviousSpeed(prevSpeed, prevAcceleration);
1948 : }
1949 :
1950 : void
1951 1596 : Vehicle::setSpeedMode(const std::string& vehID, int speedMode) {
1952 1596 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1953 1596 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1954 1596 : if (veh == nullptr) {
1955 2 : WRITE_WARNING("setSpeedMode not yet implemented for meso");
1956 2 : return;
1957 : }
1958 :
1959 1594 : veh->getInfluencer().setSpeedMode(speedMode);
1960 : }
1961 :
1962 : void
1963 450 : Vehicle::setLaneChangeMode(const std::string& vehID, int laneChangeMode) {
1964 450 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
1965 450 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
1966 450 : if (veh == nullptr) {
1967 0 : WRITE_ERROR("setLaneChangeMode not applicable for meso");
1968 0 : return;
1969 : }
1970 :
1971 450 : veh->getInfluencer().setLaneChangeMode(laneChangeMode);
1972 : }
1973 :
1974 : void
1975 225 : Vehicle::setRoutingMode(const std::string& vehID, int routingMode) {
1976 225 : Helper::getVehicle(vehID)->setRoutingMode(routingMode);
1977 225 : }
1978 :
1979 : void
1980 252 : Vehicle::setType(const std::string& vehID, const std::string& typeID) {
1981 252 : MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
1982 252 : if (vehicleType == nullptr) {
1983 0 : throw TraCIException("Vehicle type '" + typeID + "' is not known");
1984 : }
1985 252 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
1986 252 : veh->replaceVehicleType(vehicleType);
1987 252 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
1988 252 : if (microVeh != nullptr && microVeh->isOnRoad()) {
1989 234 : microVeh->updateBestLanes(true);
1990 234 : microVeh->updateLaneBruttoSum();
1991 : }
1992 252 : }
1993 :
1994 : void
1995 27 : Vehicle::setRouteID(const std::string& vehID, const std::string& routeID) {
1996 27 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
1997 27 : ConstMSRoutePtr r = MSRoute::dictionary(routeID);
1998 27 : if (r == nullptr) {
1999 2 : throw TraCIException("The route '" + routeID + "' is not known.");
2000 : }
2001 26 : if (SUMOVehicleParserHelper::isInternalRouteID(routeID)) {
2002 3 : WRITE_WARNINGF(TL("Internal routes receive an ID starting with '!' and must not be referenced in other vehicle or flow definitions. Please remove all references to route '%' in case it is internal."), routeID);
2003 : }
2004 : std::string msg;
2005 52 : if (!veh->hasValidRoute(msg, r)) {
2006 5 : WRITE_WARNINGF(TL("Invalid route replacement for vehicle '%'. %"), veh->getID(), msg);
2007 1 : if (MSGlobals::gCheckRoutes) {
2008 2 : throw TraCIException("Route replacement failed for " + veh->getID());
2009 : }
2010 : }
2011 :
2012 : std::string errorMsg;
2013 76 : if (!veh->replaceRoute(r, "traci:setRouteID", veh->getLane() == nullptr, 0, true, true, &errorMsg)) {
2014 2 : throw TraCIException("Route replacement failed for vehicle '" + veh->getID() + "' (" + errorMsg + ").");
2015 : }
2016 24 : }
2017 :
2018 : void
2019 1 : Vehicle::setRoute(const std::string& vehID, const std::string& edgeID) {
2020 3 : setRoute(vehID, std::vector<std::string>({edgeID}));
2021 0 : }
2022 :
2023 :
2024 : void
2025 38 : Vehicle::setRoute(const std::string& vehID, const std::vector<std::string>& edgeIDs) {
2026 38 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2027 : ConstMSEdgeVector edges;
2028 38 : const bool onInit = veh->getLane() == nullptr;
2029 : try {
2030 71 : MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
2031 33 : if (edges.size() > 0 && edges.front()->isInternal()) {
2032 9 : if (edges.size() == 1) {
2033 : // avoid crashing due to lack of normal edges in route (#5390)
2034 5 : edges.push_back(edges.back()->getLanes()[0]->getNextNormal());
2035 : } else {
2036 : // avoid internal edge in final route
2037 4 : if (edges.front() == &veh->getLane()->getEdge()) {
2038 : edges.erase(edges.begin());
2039 : }
2040 : }
2041 : }
2042 5 : } catch (ProcessError& e) {
2043 10 : throw TraCIException("Invalid edge list for vehicle '" + veh->getID() + "' (" + e.what() + ")");
2044 5 : }
2045 : std::string errorMsg;
2046 69 : if (!veh->replaceRouteEdges(edges, -1, 0, "traci:setRoute", onInit, true, true, &errorMsg)) {
2047 6 : throw TraCIException("Route replacement failed for vehicle '" + veh->getID() + "' (" + errorMsg + ").");
2048 : }
2049 38 : }
2050 :
2051 :
2052 : void
2053 9 : Vehicle::setLateralLanePosition(const std::string& vehID, double posLat) {
2054 9 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2055 9 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
2056 9 : if (veh != nullptr) {
2057 : veh->setLateralPositionOnLane(posLat);
2058 : } else {
2059 2 : WRITE_ERROR("setLateralLanePosition not applicable for meso");
2060 : }
2061 9 : }
2062 :
2063 :
2064 : void
2065 294 : Vehicle::updateBestLanes(const std::string& vehID) {
2066 294 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2067 294 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
2068 294 : if (veh == nullptr) {
2069 1 : WRITE_ERROR("updateBestLanes not applicable for meso");
2070 1 : return;
2071 : }
2072 293 : if (veh->isOnRoad()) {
2073 285 : veh->updateBestLanes(true);
2074 : }
2075 : }
2076 :
2077 :
2078 : void
2079 196 : Vehicle::setAdaptedTraveltime(const std::string& vehID, const std::string& edgeID,
2080 : double time, double begSeconds, double endSeconds) {
2081 196 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2082 196 : MSEdge* edge = MSEdge::dictionary(edgeID);
2083 196 : if (edge == nullptr) {
2084 0 : throw TraCIException("Edge '" + edgeID + "' is not known.");
2085 : }
2086 196 : if (time != INVALID_DOUBLE_VALUE) {
2087 : // add time
2088 187 : if (begSeconds == 0 && endSeconds == std::numeric_limits<double>::max()) {
2089 : // clean up old values before setting whole range
2090 159 : while (veh->getWeightsStorage().knowsTravelTime(edge)) {
2091 0 : veh->getWeightsStorage().removeTravelTime(edge);
2092 : }
2093 : }
2094 187 : veh->getWeightsStorage().addTravelTime(edge, begSeconds, endSeconds, time);
2095 : } else {
2096 : // remove time
2097 18 : while (veh->getWeightsStorage().knowsTravelTime(edge)) {
2098 9 : veh->getWeightsStorage().removeTravelTime(edge);
2099 : }
2100 : }
2101 196 : }
2102 :
2103 :
2104 : void
2105 32 : Vehicle::setEffort(const std::string& vehID, const std::string& edgeID,
2106 : double effort, double begSeconds, double endSeconds) {
2107 32 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2108 32 : MSEdge* edge = MSEdge::dictionary(edgeID);
2109 32 : if (edge == nullptr) {
2110 0 : throw TraCIException("Edge '" + edgeID + "' is not known.");
2111 : }
2112 32 : if (effort != INVALID_DOUBLE_VALUE) {
2113 : // add effort
2114 23 : if (begSeconds == 0 && endSeconds == std::numeric_limits<double>::max()) {
2115 : // clean up old values before setting whole range
2116 9 : while (veh->getWeightsStorage().knowsEffort(edge)) {
2117 0 : veh->getWeightsStorage().removeEffort(edge);
2118 : }
2119 : }
2120 23 : veh->getWeightsStorage().addEffort(edge, begSeconds, endSeconds, effort);
2121 : } else {
2122 : // remove effort
2123 18 : while (veh->getWeightsStorage().knowsEffort(edge)) {
2124 9 : veh->getWeightsStorage().removeEffort(edge);
2125 : }
2126 : }
2127 32 : }
2128 :
2129 :
2130 : void
2131 365 : Vehicle::rerouteTraveltime(const std::string& vehID, const bool currentTravelTimes) {
2132 365 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2133 365 : const int routingMode = veh->getRoutingMode();
2134 365 : if (currentTravelTimes && routingMode == ROUTING_MODE_DEFAULT) {
2135 : veh->setRoutingMode(ROUTING_MODE_AGGREGATED_CUSTOM);
2136 : }
2137 365 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), "traci:rerouteTraveltime",
2138 365 : veh->getRouterTT(), isOnInit(vehID));
2139 365 : if (currentTravelTimes && routingMode == ROUTING_MODE_DEFAULT) {
2140 : veh->setRoutingMode(routingMode);
2141 : }
2142 365 : }
2143 :
2144 :
2145 : void
2146 11 : Vehicle::rerouteEffort(const std::string& vehID) {
2147 11 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2148 11 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), "traci:rerouteEffort",
2149 22 : MSNet::getInstance()->getRouterEffort(veh->getRNGIndex()), isOnInit(vehID));
2150 11 : }
2151 :
2152 :
2153 : void
2154 22 : Vehicle::setSignals(const std::string& vehID, int signals) {
2155 22 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2156 22 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
2157 22 : if (veh == nullptr) {
2158 1 : WRITE_ERROR("setSignals not applicable for meso");
2159 1 : return;
2160 : }
2161 :
2162 : // set influencer to make the change persistent
2163 21 : veh->getInfluencer().setSignals(signals);
2164 : // set them now so that getSignals returns the correct value
2165 : veh->switchOffSignal(0x0fffffff);
2166 21 : if (signals >= 0) {
2167 : veh->switchOnSignal(signals);
2168 : }
2169 : }
2170 :
2171 :
2172 : void
2173 502 : Vehicle::moveTo(const std::string& vehID, const std::string& laneID, double pos, int reason) {
2174 502 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2175 502 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
2176 502 : if (veh == nullptr) {
2177 10 : WRITE_WARNING("moveTo not yet implemented for meso");
2178 375 : return;
2179 : }
2180 :
2181 492 : MSLane* l = MSLane::dictionary(laneID);
2182 492 : if (l == nullptr) {
2183 2 : throw TraCIException("Unknown lane '" + laneID + "'.");
2184 : }
2185 491 : if (veh->getLane() == l) {
2186 365 : veh->setTentativeLaneAndPosition(l, pos, veh->getLateralPositionOnLane());
2187 365 : return;
2188 : }
2189 : MSEdge* destinationEdge = &l->getEdge();
2190 126 : const MSEdge* destinationRouteEdge = destinationEdge->getNormalBefore();
2191 126 : if (!veh->isOnRoad() && veh->getParameter().wasSet(VEHPARS_FORCE_REROUTE) && veh->getRoute().getEdges().size() == 2) {
2192 : // it's a trip that wasn't routeted yet (likely because the vehicle was added in this step. Find a route now
2193 10 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), "traci:moveTo-tripInsertion",
2194 : veh->getRouterTT(), true);
2195 : }
2196 : // find edge in the remaining route
2197 126 : MSRouteIterator it = std::find(veh->getCurrentRouteEdge(), veh->getRoute().end(), destinationRouteEdge);
2198 126 : if (it == veh->getRoute().end()) {
2199 : // find edge in the edges that were already passed
2200 35 : it = std::find(veh->getRoute().begin(), veh->getRoute().end(), destinationRouteEdge);
2201 : }
2202 126 : if (it == veh->getRoute().end() ||
2203 : // internal edge must continue the route
2204 10 : (destinationEdge->isInternal() &&
2205 10 : ((it + 1) == veh->getRoute().end()
2206 10 : || l->getNextNormal() != *(it + 1)))) {
2207 32 : throw TraCIException("Lane '" + laneID + "' is not on the route of vehicle '" + vehID + "'.");
2208 : }
2209 110 : Position oldPos = vehicle->getPosition();
2210 110 : veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT);
2211 110 : if (veh->getLane() != nullptr) {
2212 : // correct odometer which gets incremented via onRemovalFromNet->leaveLane
2213 80 : veh->addToOdometer(-veh->getLane()->getLength());
2214 80 : veh->getMutableLane()->removeVehicle(veh, MSMoveReminder::NOTIFICATION_TELEPORT, false);
2215 : } else {
2216 30 : veh->setTentativeLaneAndPosition(l, pos);
2217 : }
2218 110 : const int oldRouteIndex = veh->getRoutePosition();
2219 110 : const int newRouteIndex = (int)(it - veh->getRoute().begin());
2220 110 : if (oldRouteIndex > newRouteIndex) {
2221 : // more odometer correction needed
2222 : veh->addToOdometer(-l->getLength());
2223 : }
2224 110 : veh->resetRoutePosition(newRouteIndex, veh->getParameter().departLaneProcedure);
2225 110 : if (!veh->isOnRoad()) {
2226 110 : MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh);
2227 110 : MSVehicleTransfer::getInstance()->remove(veh);
2228 : }
2229 : MSMoveReminder::Notification moveReminderReason;
2230 110 : if (veh->hasDeparted()) {
2231 80 : if (reason == MOVE_TELEPORT) {
2232 : moveReminderReason = MSMoveReminder::NOTIFICATION_TELEPORT;
2233 77 : } else if (reason == MOVE_NORMAL) {
2234 : moveReminderReason = MSMoveReminder::NOTIFICATION_JUNCTION;
2235 74 : } else if (reason == MOVE_AUTOMATIC) {
2236 : Position newPos = l->geometryPositionAtOffset(pos);
2237 : const double dist = newPos.distanceTo2D(oldPos);
2238 74 : if (dist < SPEED2DIST(veh->getMaxSpeed())) {
2239 : moveReminderReason = MSMoveReminder::NOTIFICATION_JUNCTION;
2240 : } else {
2241 : moveReminderReason = MSMoveReminder::NOTIFICATION_TELEPORT;
2242 : }
2243 : } else {
2244 0 : throw TraCIException("Invalid moveTo reason '" + toString(reason) + "' for vehicle '" + vehID + "'.");
2245 : }
2246 : } else {
2247 : moveReminderReason = MSMoveReminder::NOTIFICATION_DEPARTED;
2248 : }
2249 110 : l->forceVehicleInsertion(veh, pos, moveReminderReason);
2250 : }
2251 :
2252 :
2253 : void
2254 17 : Vehicle::setActionStepLength(const std::string& vehID, double actionStepLength, bool resetActionOffset) {
2255 17 : if (actionStepLength < 0.0) {
2256 0 : WRITE_ERROR("Invalid action step length (<0). Ignoring command setActionStepLength().");
2257 0 : return;
2258 : }
2259 17 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2260 17 : MSVehicle* veh = dynamic_cast<MSVehicle*>(vehicle);
2261 17 : if (veh == nullptr) {
2262 3 : WRITE_ERROR("setActionStepLength not applicable for meso");
2263 3 : return;
2264 : }
2265 :
2266 14 : if (actionStepLength == 0.) {
2267 0 : veh->resetActionOffset();
2268 : } else {
2269 14 : veh->setActionStepLength(actionStepLength, resetActionOffset);
2270 : }
2271 : }
2272 :
2273 :
2274 : void
2275 4 : Vehicle::setBoardingDuration(const std::string& vehID, double boardingDuration) {
2276 : try {
2277 4 : checkTimeBounds(boardingDuration);
2278 0 : } catch (ProcessError&) {
2279 0 : throw TraCIException("BoardingDuration parameter exceeds the time value range.");
2280 0 : }
2281 4 : Helper::getVehicle(vehID)->getSingularType().setBoardingDuration(TIME2STEPS(boardingDuration));
2282 4 : }
2283 :
2284 :
2285 : void
2286 27 : Vehicle::setImpatience(const std::string& vehID, double impatience) {
2287 27 : MSBaseVehicle* vehicle = Helper::getVehicle(vehID);
2288 27 : const double normalImpatience = vehicle->getImpatience();
2289 27 : vehicle->getBaseInfluencer().setExtraImpatience(impatience - normalImpatience);
2290 27 : }
2291 :
2292 :
2293 : void
2294 30 : Vehicle::remove(const std::string& vehID, char reason) {
2295 30 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2296 : MSMoveReminder::Notification n = MSMoveReminder::NOTIFICATION_ARRIVED;
2297 : switch (reason) {
2298 : case REMOVE_TELEPORT:
2299 : // XXX semantics unclear
2300 : // n = MSMoveReminder::NOTIFICATION_TELEPORT;
2301 : n = MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED;
2302 : break;
2303 : case REMOVE_PARKING:
2304 : // XXX semantics unclear
2305 : // n = MSMoveReminder::NOTIFICATION_PARKING;
2306 : n = MSMoveReminder::NOTIFICATION_ARRIVED;
2307 : break;
2308 : case REMOVE_ARRIVED:
2309 : n = MSMoveReminder::NOTIFICATION_ARRIVED;
2310 : break;
2311 : case REMOVE_VAPORIZED:
2312 : n = MSMoveReminder::NOTIFICATION_VAPORIZED_TRACI;
2313 : break;
2314 : case REMOVE_TELEPORT_ARRIVED:
2315 : n = MSMoveReminder::NOTIFICATION_TELEPORT_ARRIVED;
2316 : break;
2317 0 : default:
2318 0 : throw TraCIException("Unknown removal status.");
2319 : }
2320 30 : if (veh->hasDeparted()) {
2321 26 : veh->onRemovalFromNet(n);
2322 26 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
2323 26 : if (microVeh != nullptr) {
2324 24 : if (veh->getLane() != nullptr) {
2325 24 : microVeh->getMutableLane()->removeVehicle(dynamic_cast<MSVehicle*>(veh), n);
2326 : }
2327 24 : MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
2328 : }
2329 26 : MSNet::getInstance()->getVehicleControl().removePending();
2330 : } else {
2331 4 : MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh);
2332 4 : MSNet::getInstance()->getVehicleControl().deleteVehicle(veh, true);
2333 : }
2334 30 : }
2335 :
2336 :
2337 : void
2338 179 : Vehicle::setColor(const std::string& vehID, const TraCIColor& col) {
2339 179 : const SUMOVehicleParameter& p = Helper::getVehicle(vehID)->getParameter();
2340 179 : p.color.set((unsigned char)col.r, (unsigned char)col.g, (unsigned char)col.b, (unsigned char)col.a);
2341 179 : p.parametersSet |= VEHPARS_COLOR_SET;
2342 179 : }
2343 :
2344 :
2345 : void
2346 6492 : Vehicle::setSpeedFactor(const std::string& vehID, double factor) {
2347 6492 : Helper::getVehicle(vehID)->setChosenSpeedFactor(factor);
2348 6492 : }
2349 :
2350 :
2351 : void
2352 15 : Vehicle::setLine(const std::string& vehID, const std::string& line) {
2353 15 : Helper::getVehicle(vehID)->getParameter().line = line;
2354 15 : }
2355 :
2356 :
2357 : void
2358 19 : Vehicle::setVia(const std::string& vehID, const std::vector<std::string>& edgeList) {
2359 19 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2360 : try {
2361 : // ensure edges exist
2362 : ConstMSEdgeVector edges;
2363 19 : MSEdge::parseEdgesList(edgeList, edges, "<via-edges>");
2364 19 : } catch (ProcessError& e) {
2365 0 : throw TraCIException(e.what());
2366 0 : }
2367 19 : veh->getParameter().via = edgeList;
2368 19 : }
2369 :
2370 :
2371 : void
2372 45 : Vehicle::setLength(const std::string& vehID, double length) {
2373 45 : Helper::getVehicle(vehID)->getSingularType().setLength(length);
2374 45 : }
2375 :
2376 :
2377 : void
2378 17 : Vehicle::setMaxSpeed(const std::string& vehID, double speed) {
2379 17 : Helper::getVehicle(vehID)->getSingularType().setMaxSpeed(speed);
2380 17 : }
2381 :
2382 :
2383 : void
2384 4 : Vehicle::setVehicleClass(const std::string& vehID, const std::string& clazz) {
2385 4 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2386 4 : veh->getSingularType().setVClass(getVehicleClassID(clazz));
2387 4 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
2388 4 : if (microVeh != nullptr && microVeh->isOnRoad()) {
2389 4 : microVeh->updateBestLanes(true);
2390 : }
2391 4 : }
2392 :
2393 :
2394 : void
2395 4 : Vehicle::setShapeClass(const std::string& vehID, const std::string& clazz) {
2396 4 : Helper::getVehicle(vehID)->getSingularType().setShape(getVehicleShapeID(clazz));
2397 4 : }
2398 :
2399 :
2400 : void
2401 10 : Vehicle::setEmissionClass(const std::string& vehID, const std::string& clazz) {
2402 10 : Helper::getVehicle(vehID)->getSingularType().setEmissionClass(PollutantsInterface::getClassByName(clazz));
2403 10 : }
2404 :
2405 :
2406 : void
2407 5 : Vehicle::setWidth(const std::string& vehID, double width) {
2408 5 : Helper::getVehicle(vehID)->getSingularType().setWidth(width);
2409 5 : }
2410 :
2411 :
2412 : void
2413 4 : Vehicle::setHeight(const std::string& vehID, double height) {
2414 4 : Helper::getVehicle(vehID)->getSingularType().setHeight(height);
2415 4 : }
2416 :
2417 :
2418 : void
2419 4 : Vehicle::setMass(const std::string& vehID, double mass) {
2420 4 : Helper::getVehicle(vehID)->getSingularType().setMass(mass);
2421 4 : }
2422 :
2423 :
2424 : void
2425 14 : Vehicle::setMinGap(const std::string& vehID, double minGap) {
2426 14 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2427 14 : veh->getSingularType().setMinGap(minGap);
2428 14 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
2429 14 : if (microVeh != nullptr && microVeh->isOnRoad()) {
2430 12 : microVeh->updateLaneBruttoSum();
2431 : }
2432 14 : }
2433 :
2434 :
2435 : void
2436 9 : Vehicle::setAccel(const std::string& vehID, double accel) {
2437 9 : Helper::getVehicle(vehID)->getSingularType().setAccel(accel);
2438 8 : }
2439 :
2440 :
2441 : void
2442 5 : Vehicle::setDecel(const std::string& vehID, double decel) {
2443 5 : VehicleType::setDecel(Helper::getVehicle(vehID)->getSingularType().getID(), decel);
2444 5 : }
2445 :
2446 :
2447 : void
2448 9 : Vehicle::setEmergencyDecel(const std::string& vehID, double decel) {
2449 9 : VehicleType::setEmergencyDecel(Helper::getVehicle(vehID)->getSingularType().getID(), decel);
2450 9 : }
2451 :
2452 :
2453 : void
2454 5 : Vehicle::setApparentDecel(const std::string& vehID, double decel) {
2455 5 : Helper::getVehicle(vehID)->getSingularType().setApparentDecel(decel);
2456 5 : }
2457 :
2458 :
2459 : void
2460 7 : Vehicle::setImperfection(const std::string& vehID, double imperfection) {
2461 7 : Helper::getVehicle(vehID)->getSingularType().setImperfection(imperfection);
2462 7 : }
2463 :
2464 :
2465 : void
2466 5 : Vehicle::setTau(const std::string& vehID, double tau) {
2467 5 : Helper::getVehicle(vehID)->getSingularType().setTau(tau);
2468 5 : }
2469 :
2470 :
2471 : void
2472 9 : Vehicle::setMinGapLat(const std::string& vehID, double minGapLat) {
2473 : try {
2474 18 : setParameter(vehID, "laneChangeModel.minGapLat", toString(minGapLat));
2475 5 : } catch (TraCIException&) {
2476 : // legacy behavior
2477 5 : Helper::getVehicle(vehID)->getSingularType().setMinGapLat(minGapLat);
2478 5 : }
2479 9 : }
2480 :
2481 :
2482 : void
2483 4 : Vehicle::setMaxSpeedLat(const std::string& vehID, double speed) {
2484 4 : Helper::getVehicle(vehID)->getSingularType().setMaxSpeedLat(speed);
2485 4 : }
2486 :
2487 :
2488 : void
2489 4 : Vehicle::setLateralAlignment(const std::string& vehID, const std::string& latAlignment) {
2490 : double lao;
2491 : LatAlignmentDefinition lad;
2492 4 : if (SUMOVTypeParameter::parseLatAlignment(latAlignment, lao, lad)) {
2493 4 : Helper::getVehicle(vehID)->getSingularType().setPreferredLateralAlignment(lad, lao);
2494 : } else {
2495 0 : throw TraCIException("Unknown value '" + latAlignment + "' when setting latAlignment for vehID '" + vehID + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
2496 : }
2497 4 : }
2498 :
2499 :
2500 : void
2501 418 : Vehicle::setParameter(const std::string& vehID, const std::string& key, const std::string& value) {
2502 418 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2503 417 : MSVehicle* microVeh = dynamic_cast<MSVehicle*>(veh);
2504 834 : if (StringUtils::startsWith(key, "device.")) {
2505 594 : StringTokenizer tok(key, ".");
2506 198 : if (tok.size() < 3) {
2507 0 : throw TraCIException("Invalid device parameter '" + key + "' for vehicle '" + vehID + "'");
2508 : }
2509 : try {
2510 594 : veh->setDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2), value);
2511 0 : } catch (InvalidArgument& e) {
2512 0 : throw TraCIException("Vehicle '" + vehID + "' does not support device parameter '" + key + "' (" + e.what() + ").");
2513 0 : }
2514 636 : } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
2515 23 : if (microVeh == nullptr) {
2516 4 : throw TraCIException("Meso Vehicle '" + vehID + "' does not support laneChangeModel parameters.");
2517 : }
2518 21 : const std::string attrName = key.substr(16);
2519 : try {
2520 21 : microVeh->getLaneChangeModel().setParameter(attrName, value);
2521 4 : } catch (InvalidArgument& e) {
2522 8 : throw TraCIException("Vehicle '" + vehID + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").");
2523 4 : }
2524 392 : } else if (StringUtils::startsWith(key, "carFollowModel.")) {
2525 21 : if (microVeh == nullptr) {
2526 0 : throw TraCIException("Meso Vehicle '" + vehID + "' does not support carFollowModel parameters.");
2527 : }
2528 : try {
2529 21 : veh->setCarFollowModelParameter(key, value);
2530 5 : } catch (InvalidArgument& e) {
2531 10 : throw TraCIException("Vehicle '" + vehID + "' does not support carFollowModel parameter '" + key + "' (" + e.what() + ").");
2532 5 : }
2533 350 : } else if (StringUtils::startsWith(key, "junctionModel.")) {
2534 : try {
2535 : // use the whole key (including junctionModel prefix)
2536 10 : veh->setJunctionModelParameter(key, value);
2537 5 : } catch (InvalidArgument& e) {
2538 : // error message includes id since it is also used for xml input
2539 10 : throw TraCIException(e.what());
2540 5 : }
2541 174 : } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
2542 27 : StringTokenizer tok(key, ".");
2543 9 : if (tok.size() != 3) {
2544 0 : throw TraCIException("Invalid request for device status change. Expected format is 'has.DEVICENAME.device'");
2545 : }
2546 9 : const std::string deviceName = tok.get(1);
2547 : bool create;
2548 : try {
2549 9 : create = StringUtils::toBool(value);
2550 0 : } catch (BoolFormatException&) {
2551 0 : throw TraCIException("Changing device status requires a 'true' or 'false'");
2552 0 : }
2553 9 : if (!create) {
2554 0 : throw TraCIException("Device removal is not supported for device of type '" + deviceName + "'");
2555 : }
2556 : try {
2557 9 : veh->createDevice(deviceName);
2558 0 : } catch (InvalidArgument& e) {
2559 0 : throw TraCIException("Cannot create vehicle device (" + std::string(e.what()) + ").");
2560 0 : }
2561 9 : } else {
2562 156 : ((SUMOVehicleParameter&)veh->getParameter()).setParameter(key, value);
2563 : }
2564 401 : }
2565 :
2566 :
2567 : void
2568 40 : Vehicle::highlight(const std::string& vehID, const TraCIColor& col, double size, const int alphaMax, const double duration, const int type) {
2569 :
2570 : // NOTE: Code is duplicated in large parts in POI.cpp
2571 40 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2572 :
2573 : // Center of the highlight circle
2574 40 : Position center = veh->getPosition();
2575 40 : const double l2 = veh->getLength() * 0.5;
2576 40 : center.sub(cos(veh->getAngle())*l2, sin(veh->getAngle())*l2);
2577 : // Size of the highlight circle
2578 40 : if (size <= 0) {
2579 40 : size = veh->getLength() * 0.7;
2580 : }
2581 : // Make polygon shape
2582 : const unsigned int nPoints = 34;
2583 40 : const PositionVector circlePV = GeomHelper::makeRing(size, size + 1., center, nPoints);
2584 40 : TraCIPositionVector circle = Helper::makeTraCIPositionVector(circlePV);
2585 :
2586 : #ifdef DEBUG_DYNAMIC_SHAPES
2587 : std::cout << SIMTIME << " Vehicle::highlight() for vehicle '" << vehID << "'\n"
2588 : << " circle: " << circlePV << std::endl;
2589 : #endif
2590 :
2591 : // Find a free polygon id
2592 40 : int i = 0;
2593 80 : std::string polyID = veh->getID() + "_hl" + toString(i);
2594 136 : while (Polygon::exists(polyID)) {
2595 16 : polyID = veh->getID() + "_hl" + toString(++i);
2596 : }
2597 : // Line width
2598 : double lw = 0.;
2599 : // Layer
2600 : double lyr = 0.;
2601 40 : if (MSNet::getInstance()->isGUINet()) {
2602 : lyr = GLO_VEHICLE + 0.01;
2603 16 : lyr += (type + 1) / 257.;
2604 : }
2605 : // Make Polygon
2606 80 : Polygon::addHighlightPolygon(vehID, type, polyID, circle, col, true, "highlight", (int)lyr, lw);
2607 :
2608 : // Animation time line
2609 : double maxAttack = 1.0; // maximal fade-in time
2610 : std::vector<double> timeSpan;
2611 40 : if (duration > 0.) {
2612 64 : timeSpan = {0, MIN2(maxAttack, duration / 3.), 2.*duration / 3., duration};
2613 : }
2614 : // Alpha time line
2615 : std::vector<double> alphaSpan;
2616 40 : if (alphaMax > 0.) {
2617 48 : alphaSpan = {0., (double) alphaMax, (double)(alphaMax) / 3., 0.};
2618 : }
2619 : // Attach dynamics
2620 40 : Polygon::addDynamics(polyID, vehID, timeSpan, alphaSpan, false, true);
2621 80 : }
2622 :
2623 : void
2624 197 : Vehicle::dispatchTaxi(const std::string& vehID, const std::vector<std::string>& reservations) {
2625 197 : MSBaseVehicle* veh = Helper::getVehicle(vehID);
2626 197 : MSDevice_Taxi* taxi = static_cast<MSDevice_Taxi*>(veh->getDevice(typeid(MSDevice_Taxi)));
2627 197 : if (!veh->hasDeparted()) {
2628 10 : throw TraCIException("Vehicle '" + vehID + "' has not yet departed");
2629 : }
2630 192 : if (taxi == nullptr) {
2631 0 : throw TraCIException("Vehicle '" + vehID + "' is not a taxi");
2632 : }
2633 : MSDispatch* dispatcher = MSDevice_Taxi::getDispatchAlgorithm();
2634 192 : if (dispatcher == nullptr) {
2635 0 : throw TraCIException("Cannot dispatch taxi because no reservations have been made");
2636 : }
2637 192 : MSDispatch_TraCI* traciDispatcher = dynamic_cast<MSDispatch_TraCI*>(dispatcher);
2638 192 : if (traciDispatcher == nullptr) {
2639 0 : throw TraCIException("device.taxi.dispatch-algorithm 'traci' has not been loaded");
2640 : }
2641 192 : if (reservations.size() == 0) {
2642 0 : throw TraCIException("No reservations have been specified for vehicle '" + vehID + "'");
2643 : }
2644 : try {
2645 192 : traciDispatcher->interpretDispatch(taxi, reservations);
2646 4 : } catch (InvalidArgument& e) {
2647 8 : throw TraCIException("Could not interpret reservations for vehicle '" + vehID + "' (" + e.what() + ").");
2648 4 : }
2649 188 : }
2650 :
2651 30592 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(Vehicle, VEHICLE)
2652 :
2653 :
2654 : void
2655 33 : Vehicle::subscribeLeader(const std::string& vehID, double dist, double begin, double end) {
2656 33 : subscribe(vehID, std::vector<int>({ libsumo::VAR_LEADER }), begin, end,
2657 99 : libsumo::TraCIResults({ {libsumo::VAR_LEADER, std::make_shared<libsumo::TraCIDouble>(dist)} }));
2658 33 : }
2659 :
2660 :
2661 : void
2662 85 : Vehicle::addSubscriptionFilterLanes(const std::vector<int>& lanes, bool noOpposite, double downstreamDist, double upstreamDist) {
2663 85 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_LANES);
2664 85 : if (s != nullptr) {
2665 85 : s->filterLanes = lanes;
2666 : }
2667 85 : if (noOpposite) {
2668 2 : addSubscriptionFilterNoOpposite();
2669 : }
2670 85 : if (downstreamDist != INVALID_DOUBLE_VALUE) {
2671 4 : addSubscriptionFilterDownstreamDistance(downstreamDist);
2672 : }
2673 85 : if (upstreamDist != INVALID_DOUBLE_VALUE) {
2674 4 : addSubscriptionFilterUpstreamDistance(upstreamDist);
2675 : }
2676 85 : }
2677 :
2678 :
2679 : void
2680 27 : Vehicle::addSubscriptionFilterNoOpposite() {
2681 27 : Helper::addSubscriptionFilter(SUBS_FILTER_NOOPPOSITE);
2682 27 : }
2683 :
2684 :
2685 : void
2686 101 : Vehicle::addSubscriptionFilterDownstreamDistance(double dist) {
2687 101 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_DOWNSTREAM_DIST);
2688 101 : if (s != nullptr) {
2689 101 : s->filterDownstreamDist = dist;
2690 : }
2691 101 : }
2692 :
2693 :
2694 : void
2695 85 : Vehicle::addSubscriptionFilterUpstreamDistance(double dist) {
2696 85 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_UPSTREAM_DIST);
2697 85 : if (s != nullptr) {
2698 85 : s->filterUpstreamDist = dist;
2699 : }
2700 85 : }
2701 :
2702 :
2703 : void
2704 2 : Vehicle::addSubscriptionFilterCFManeuver(double downstreamDist, double upstreamDist) {
2705 2 : addSubscriptionFilterLeadFollow(std::vector<int>({0}));
2706 2 : if (downstreamDist != INVALID_DOUBLE_VALUE) {
2707 0 : addSubscriptionFilterDownstreamDistance(downstreamDist);
2708 : }
2709 2 : if (upstreamDist != INVALID_DOUBLE_VALUE) {
2710 0 : addSubscriptionFilterUpstreamDistance(upstreamDist);
2711 : }
2712 :
2713 2 : }
2714 :
2715 :
2716 : void
2717 8 : Vehicle::addSubscriptionFilterLCManeuver(int direction, bool noOpposite, double downstreamDist, double upstreamDist) {
2718 : std::vector<int> lanes;
2719 8 : if (direction == INVALID_INT_VALUE) {
2720 : // Using default: both directions
2721 2 : lanes = std::vector<int>({-1, 0, 1});
2722 6 : } else if (direction != -1 && direction != 1) {
2723 0 : WRITE_WARNINGF(TL("Ignoring lane change subscription filter with non-neighboring lane offset direction=%."), direction);
2724 : } else {
2725 6 : lanes = std::vector<int>({0, direction});
2726 : }
2727 8 : addSubscriptionFilterLeadFollow(lanes);
2728 8 : if (noOpposite) {
2729 0 : addSubscriptionFilterNoOpposite();
2730 : }
2731 8 : if (downstreamDist != INVALID_DOUBLE_VALUE) {
2732 0 : addSubscriptionFilterDownstreamDistance(downstreamDist);
2733 : }
2734 8 : if (upstreamDist != INVALID_DOUBLE_VALUE) {
2735 0 : addSubscriptionFilterUpstreamDistance(upstreamDist);
2736 : }
2737 8 : }
2738 :
2739 :
2740 : void
2741 10 : Vehicle::addSubscriptionFilterLeadFollow(const std::vector<int>& lanes) {
2742 10 : Helper::addSubscriptionFilter(SUBS_FILTER_LEAD_FOLLOW);
2743 10 : addSubscriptionFilterLanes(lanes);
2744 10 : }
2745 :
2746 :
2747 : void
2748 16 : Vehicle::addSubscriptionFilterTurn(double downstreamDist, double foeDistToJunction) {
2749 16 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_TURN);
2750 16 : if (downstreamDist != INVALID_DOUBLE_VALUE) {
2751 16 : addSubscriptionFilterDownstreamDistance(downstreamDist);
2752 : }
2753 16 : if (foeDistToJunction != INVALID_DOUBLE_VALUE) {
2754 16 : s->filterFoeDistToJunction = foeDistToJunction;
2755 : }
2756 16 : }
2757 :
2758 :
2759 : void
2760 6 : Vehicle::addSubscriptionFilterVClass(const std::vector<std::string>& vClasses) {
2761 6 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_VCLASS);
2762 6 : if (s != nullptr) {
2763 6 : s->filterVClasses = parseVehicleClasses(vClasses);
2764 : }
2765 6 : }
2766 :
2767 :
2768 : void
2769 6 : Vehicle::addSubscriptionFilterVType(const std::vector<std::string>& vTypes) {
2770 6 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_VTYPE);
2771 6 : if (s != nullptr) {
2772 : s->filterVTypes.insert(vTypes.begin(), vTypes.end());
2773 : }
2774 6 : }
2775 :
2776 :
2777 : void
2778 16 : Vehicle::addSubscriptionFilterFieldOfVision(double openingAngle) {
2779 16 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_FIELD_OF_VISION);
2780 16 : if (s != nullptr) {
2781 16 : s->filterFieldOfVisionOpeningAngle = openingAngle;
2782 : }
2783 16 : }
2784 :
2785 :
2786 : void
2787 15 : Vehicle::addSubscriptionFilterLateralDistance(double lateralDist, double downstreamDist, double upstreamDist) {
2788 15 : Subscription* s = Helper::addSubscriptionFilter(SUBS_FILTER_LATERAL_DIST);
2789 14 : if (s != nullptr) {
2790 14 : s->filterLateralDist = lateralDist;
2791 : }
2792 14 : if (downstreamDist != INVALID_DOUBLE_VALUE) {
2793 14 : addSubscriptionFilterDownstreamDistance(downstreamDist);
2794 : }
2795 14 : if (upstreamDist != INVALID_DOUBLE_VALUE) {
2796 14 : addSubscriptionFilterUpstreamDistance(upstreamDist);
2797 : }
2798 14 : }
2799 :
2800 :
2801 : void
2802 17126 : Vehicle::storeShape(const std::string& id, PositionVector& shape) {
2803 17126 : shape.push_back(Helper::getVehicle(id)->getPosition());
2804 17126 : }
2805 :
2806 :
2807 : std::shared_ptr<VariableWrapper>
2808 264 : Vehicle::makeWrapper() {
2809 264 : return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
2810 : }
2811 :
2812 :
2813 : bool
2814 9646782 : Vehicle::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
2815 9646782 : switch (variable) {
2816 126367 : case TRACI_ID_LIST:
2817 126367 : return wrapper->wrapStringList(objID, variable, getIDList());
2818 85 : case ID_COUNT:
2819 85 : return wrapper->wrapInt(objID, variable, getIDCount());
2820 1007161 : case VAR_POSITION:
2821 1007161 : return wrapper->wrapPosition(objID, variable, getPosition(objID));
2822 1276 : case VAR_POSITION3D:
2823 1276 : return wrapper->wrapPosition(objID, variable, getPosition(objID, true));
2824 247 : case VAR_ANGLE:
2825 247 : return wrapper->wrapDouble(objID, variable, getAngle(objID));
2826 169243 : case VAR_SPEED:
2827 169243 : return wrapper->wrapDouble(objID, variable, getSpeed(objID));
2828 46 : case VAR_SPEED_LAT:
2829 46 : return wrapper->wrapDouble(objID, variable, getLateralSpeed(objID));
2830 4087218 : case VAR_ROAD_ID:
2831 8174436 : return wrapper->wrapString(objID, variable, getRoadID(objID));
2832 2075 : case VAR_SPEED_WITHOUT_TRACI:
2833 2075 : return wrapper->wrapDouble(objID, variable, getSpeedWithoutTraCI(objID));
2834 6 : case VAR_SLOPE:
2835 6 : return wrapper->wrapDouble(objID, variable, getSlope(objID));
2836 34113 : case VAR_LANE_ID:
2837 68217 : return wrapper->wrapString(objID, variable, getLaneID(objID));
2838 30147 : case VAR_LANE_INDEX:
2839 30147 : return wrapper->wrapInt(objID, variable, getLaneIndex(objID));
2840 66 : case VAR_SEGMENT_ID:
2841 129 : return wrapper->wrapString(objID, variable, getSegmentID(objID));
2842 63 : case VAR_SEGMENT_INDEX:
2843 63 : return wrapper->wrapInt(objID, variable, getSegmentIndex(objID));
2844 207 : case VAR_TYPE:
2845 409 : return wrapper->wrapString(objID, variable, getTypeID(objID));
2846 75 : case VAR_ROUTE_ID:
2847 145 : return wrapper->wrapString(objID, variable, getRouteID(objID));
2848 45 : case VAR_DEPARTURE:
2849 45 : return wrapper->wrapDouble(objID, variable, getDeparture(objID));
2850 45 : case VAR_DEPART_DELAY:
2851 45 : return wrapper->wrapDouble(objID, variable, getDepartDelay(objID));
2852 2010 : case VAR_ROUTE_INDEX:
2853 2010 : return wrapper->wrapInt(objID, variable, getRouteIndex(objID));
2854 595 : case VAR_COLOR:
2855 595 : return wrapper->wrapColor(objID, variable, getColor(objID));
2856 4066965 : case VAR_LANEPOSITION:
2857 4066965 : return wrapper->wrapDouble(objID, variable, getLanePosition(objID));
2858 1967 : case VAR_LANEPOSITION_LAT:
2859 1967 : return wrapper->wrapDouble(objID, variable, getLateralLanePosition(objID));
2860 247 : case VAR_CO2EMISSION:
2861 247 : return wrapper->wrapDouble(objID, variable, getCO2Emission(objID));
2862 47 : case VAR_COEMISSION:
2863 47 : return wrapper->wrapDouble(objID, variable, getCOEmission(objID));
2864 47 : case VAR_HCEMISSION:
2865 47 : return wrapper->wrapDouble(objID, variable, getHCEmission(objID));
2866 47 : case VAR_PMXEMISSION:
2867 47 : return wrapper->wrapDouble(objID, variable, getPMxEmission(objID));
2868 47 : case VAR_NOXEMISSION:
2869 47 : return wrapper->wrapDouble(objID, variable, getNOxEmission(objID));
2870 257 : case VAR_FUELCONSUMPTION:
2871 257 : return wrapper->wrapDouble(objID, variable, getFuelConsumption(objID));
2872 47 : case VAR_NOISEEMISSION:
2873 47 : return wrapper->wrapDouble(objID, variable, getNoiseEmission(objID));
2874 95 : case VAR_ELECTRICITYCONSUMPTION:
2875 95 : return wrapper->wrapDouble(objID, variable, getElectricityConsumption(objID));
2876 270 : case VAR_PERSON_NUMBER:
2877 270 : return wrapper->wrapInt(objID, variable, getPersonNumber(objID));
2878 283 : case VAR_PERSON_CAPACITY:
2879 283 : return wrapper->wrapInt(objID, variable, getPersonCapacity(objID));
2880 45 : case VAR_BOARDING_DURATION:
2881 45 : return wrapper->wrapDouble(objID, variable, getBoardingDuration(objID));
2882 106 : case LAST_STEP_PERSON_ID_LIST:
2883 106 : return wrapper->wrapStringList(objID, variable, getPersonIDList(objID));
2884 139 : case VAR_WAITING_TIME:
2885 139 : return wrapper->wrapDouble(objID, variable, getWaitingTime(objID));
2886 67 : case VAR_ACCUMULATED_WAITING_TIME:
2887 67 : return wrapper->wrapDouble(objID, variable, getAccumulatedWaitingTime(objID));
2888 46 : case VAR_ROUTE_VALID:
2889 46 : return wrapper->wrapInt(objID, variable, isRouteValid(objID));
2890 2180 : case VAR_EDGES:
2891 2180 : return wrapper->wrapStringList(objID, variable, getRoute(objID));
2892 48 : case VAR_SIGNALS:
2893 48 : return wrapper->wrapInt(objID, variable, getSignals(objID));
2894 1032 : case VAR_STOPSTATE:
2895 1032 : return wrapper->wrapInt(objID, variable, getStopState(objID));
2896 376 : case VAR_DISTANCE:
2897 376 : return wrapper->wrapDouble(objID, variable, getDistance(objID));
2898 45 : case VAR_ALLOWED_SPEED:
2899 45 : return wrapper->wrapDouble(objID, variable, getAllowedSpeed(objID));
2900 110 : case VAR_SPEED_FACTOR:
2901 110 : return wrapper->wrapDouble(objID, variable, getSpeedFactor(objID));
2902 35 : case VAR_SPEEDSETMODE:
2903 35 : return wrapper->wrapInt(objID, variable, getSpeedMode(objID));
2904 140 : case VAR_LANECHANGE_MODE:
2905 140 : return wrapper->wrapInt(objID, variable, getLaneChangeMode(objID));
2906 143 : case VAR_ROUTING_MODE:
2907 143 : return wrapper->wrapInt(objID, variable, getRoutingMode(objID));
2908 46 : case VAR_LINE:
2909 92 : return wrapper->wrapString(objID, variable, getLine(objID));
2910 46 : case VAR_VIA:
2911 46 : return wrapper->wrapStringList(objID, variable, getVia(objID));
2912 2678 : case VAR_ACCELERATION:
2913 2678 : return wrapper->wrapDouble(objID, variable, getAcceleration(objID));
2914 45 : case VAR_LASTACTIONTIME:
2915 45 : return wrapper->wrapDouble(objID, variable, getLastActionTime(objID));
2916 1608 : case VAR_STOP_DELAY:
2917 1608 : return wrapper->wrapDouble(objID, variable, getStopDelay(objID));
2918 60 : case VAR_IMPATIENCE:
2919 60 : return wrapper->wrapDouble(objID, variable, getImpatience(objID));
2920 1607 : case VAR_STOP_ARRIVALDELAY:
2921 1607 : return wrapper->wrapDouble(objID, variable, getStopArrivalDelay(objID));
2922 45 : case VAR_TIMELOSS:
2923 45 : return wrapper->wrapDouble(objID, variable, getTimeLoss(objID));
2924 45 : case VAR_MINGAP_LAT:
2925 45 : return wrapper->wrapDouble(objID, variable, getMinGapLat(objID));
2926 31117 : case VAR_LEADER: {
2927 31117 : paramData->readUnsignedByte();
2928 31117 : const double dist = paramData->readDouble();
2929 62234 : return wrapper->wrapStringDoublePair(objID, variable, getLeader(objID, dist));
2930 : }
2931 176 : case VAR_FOLLOWER: {
2932 176 : paramData->readUnsignedByte();
2933 176 : const double dist = paramData->readDouble();
2934 349 : return wrapper->wrapStringDoublePair(objID, variable, getFollower(objID, dist));
2935 : }
2936 121 : case VAR_LOADED_LIST:
2937 121 : return wrapper->wrapStringList(objID, variable, getLoadedIDList());
2938 96 : case VAR_TELEPORTING_LIST:
2939 96 : return wrapper->wrapStringList(objID, variable, getTeleportingIDList());
2940 47581 : case libsumo::VAR_PARAMETER:
2941 47581 : paramData->readUnsignedByte();
2942 95140 : return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
2943 20 : case libsumo::VAR_PARAMETER_WITH_KEY:
2944 20 : paramData->readUnsignedByte();
2945 40 : return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
2946 : case VAR_TAXI_FLEET:
2947 : // we cannot use the general fall through here because we do not have an object id
2948 : return false;
2949 19808 : default:
2950 39604 : return VehicleType::handleVariableWithID(objID, getTypeID(objID), variable, wrapper, paramData);
2951 : }
2952 : }
2953 :
2954 :
2955 : }
2956 :
2957 :
2958 : /****************************************************************************/
|