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