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