Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 : // Copyright (C) 2012-2017 German Aerospace Center (DLR) and others.
4 : /****************************************************************************/
5 : //
6 : // This program and the accompanying materials
7 : // are made available under the terms of the Eclipse Public License v2.0
8 : // which accompanies this distribution, and is available at
9 : // http://www.eclipse.org/legal/epl-v20.html
10 : //
11 : /****************************************************************************/
12 : /// @file TraCI_Vehicle.cpp
13 : /// @author Jakob Erdmann
14 : /// @date 15.03.2017
15 : /// @version $Id$
16 : ///
17 : // C++ Vehicle API
18 : /****************************************************************************/
19 :
20 : // ===========================================================================
21 : // included modules
22 : // ===========================================================================
23 : #ifdef _MSC_VER
24 : #include <windows_config.h>
25 : #else
26 : #include <config.h>
27 : #endif
28 :
29 : #include <utils/geom/GeomHelper.h>
30 : #include <utils/common/StringTokenizer.h>
31 : #include <utils/common/StringUtils.h>
32 : #include <utils/common/TplConvert.h>
33 : #include <utils/emissions/PollutantsInterface.h>
34 : #include <utils/xml/SUMOVehicleParserHelper.h>
35 : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
36 : #include <microsim/lcmodels/MSAbstractLaneChangeModel.h>
37 : #include <microsim/devices/MSDevice.h>
38 : #include <microsim/MSEdgeWeightsStorage.h>
39 : #include <microsim/MSVehicle.h>
40 : #include <microsim/MSVehicleControl.h>
41 : #include <microsim/MSVehicleType.h>
42 : #include <microsim/MSInsertionControl.h>
43 : #include <microsim/MSNet.h>
44 : #include <microsim/MSEdge.h>
45 : #include <microsim/MSLane.h>
46 : #include <traci-server/TraCIDefs.h>
47 : #include <traci-server/TraCIConstants.h>
48 : #include "TraCI.h"
49 : #include "TraCI_Vehicle.h"
50 :
51 :
52 : // ===========================================================================
53 : // member definitions
54 : // ===========================================================================
55 :
56 : MSVehicle*
57 4525566 : TraCI_Vehicle::getVehicle(const std::string& id) {
58 4525566 : SUMOVehicle* sumoVehicle = MSNet::getInstance()->getVehicleControl().getVehicle(id);
59 4525566 : if (sumoVehicle == 0) {
60 36 : throw TraCIException("Vehicle '" + id + "' is not known");
61 : }
62 4525530 : MSVehicle* v = dynamic_cast<MSVehicle*>(sumoVehicle);
63 4525530 : if (v == 0) {
64 0 : throw TraCIException("Vehicle '" + id + "' is not a micro-simulation vehicle");
65 : }
66 4525530 : return v;
67 : }
68 :
69 :
70 : bool
71 2937362 : TraCI_Vehicle::isVisible(const MSVehicle* veh) {
72 2937362 : return veh->isOnRoad() || veh->isParking() || veh->wasRemoteControlled();
73 : }
74 :
75 :
76 : bool
77 1942 : TraCI_Vehicle::isOnInit(const std::string& vehicleID) {
78 1942 : SUMOVehicle* sumoVehicle = MSNet::getInstance()->getVehicleControl().getVehicle(vehicleID);
79 1942 : return sumoVehicle == 0 || sumoVehicle->getLane() == 0;
80 : }
81 :
82 : std::vector<std::string>
83 239584 : TraCI_Vehicle::getIDList() {
84 239584 : std::vector<std::string> ids;
85 239584 : MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
86 1574762 : for (MSVehicleControl::constVehIt i = c.loadedVehBegin(); i != c.loadedVehEnd(); ++i) {
87 1335178 : if ((*i).second->isOnRoad() || (*i).second->isParking()) {
88 1311007 : ids.push_back((*i).first);
89 : }
90 : }
91 239584 : return ids;
92 : }
93 :
94 : int
95 25 : TraCI_Vehicle::getIDCount() {
96 25 : return (int)getIDList().size();
97 : }
98 :
99 : double
100 245492 : TraCI_Vehicle::getSpeed(const std::string& vehicleID) {
101 245492 : MSVehicle* veh = getVehicle(vehicleID);
102 245479 : return isVisible(veh) ? veh->getSpeed() : INVALID_DOUBLE_VALUE;
103 : }
104 :
105 :
106 : double
107 18 : TraCI_Vehicle::getSpeedWithoutTraCI(const std::string& vehicleID) {
108 18 : MSVehicle* veh = getVehicle(vehicleID);
109 18 : return isVisible(veh) ? veh->getSpeedWithoutTraciInfluence() : INVALID_DOUBLE_VALUE;
110 : }
111 :
112 :
113 : TraCIPosition
114 1117384 : TraCI_Vehicle::getPosition(const std::string& vehicleID) {
115 1117384 : MSVehicle* veh = getVehicle(vehicleID);
116 1117383 : if (isVisible(veh)) {
117 1117369 : return TraCI::makeTraCIPosition(veh->getPosition());
118 : } else {
119 : TraCIPosition result;
120 14 : result.x = INVALID_DOUBLE_VALUE;
121 14 : result.y = INVALID_DOUBLE_VALUE;
122 14 : result.z = INVALID_DOUBLE_VALUE;
123 14 : return result;
124 : }
125 : }
126 :
127 :
128 : double
129 100 : TraCI_Vehicle::getAngle(const std::string& vehicleID) {
130 100 : MSVehicle* veh = getVehicle(vehicleID);
131 100 : return isVisible(veh) ? GeomHelper::naviDegree(veh->getAngle()) : INVALID_DOUBLE_VALUE;
132 : }
133 :
134 :
135 : double
136 3 : TraCI_Vehicle::getSlope(const std::string& vehicleID) {
137 3 : MSVehicle* veh = getVehicle(vehicleID);
138 3 : return veh->isOnRoad() ? veh->getSlope() : INVALID_DOUBLE_VALUE;
139 : }
140 :
141 :
142 : std::string
143 1574124 : TraCI_Vehicle::getRoadID(const std::string& vehicleID) {
144 1574124 : MSVehicle* veh = getVehicle(vehicleID);
145 1574124 : return isVisible(veh) ? veh->getLane()->getEdge().getID() : "";
146 : }
147 :
148 :
149 : std::string
150 2563 : TraCI_Vehicle::getLaneID(const std::string& vehicleID) {
151 2563 : MSVehicle* veh = getVehicle(vehicleID);
152 2561 : return veh->isOnRoad() ? veh->getLane()->getID() : "";
153 : }
154 :
155 :
156 : int
157 25 : TraCI_Vehicle::getLaneIndex(const std::string& vehicleID) {
158 25 : MSVehicle* veh = getVehicle(vehicleID);
159 20 : return veh->isOnRoad() ? veh->getLane()->getIndex() : INVALID_INT_VALUE;
160 : }
161 :
162 : std::string
163 28 : TraCI_Vehicle::getTypeID(const std::string& vehicleID) {
164 28 : return getVehicle(vehicleID)->getVehicleType().getID();
165 : }
166 :
167 : std::string
168 34 : TraCI_Vehicle::getRouteID(const std::string& vehicleID) {
169 34 : return getVehicle(vehicleID)->getRoute().getID();
170 : }
171 :
172 : int
173 20 : TraCI_Vehicle::getRouteIndex(const std::string& vehicleID) {
174 20 : MSVehicle* veh = getVehicle(vehicleID);
175 20 : return veh->hasDeparted() ? veh->getRoutePosition() : INVALID_INT_VALUE;
176 : }
177 :
178 : TraCIColor
179 23 : TraCI_Vehicle::getColor(const std::string& vehicleID) {
180 23 : return TraCI::makeTraCIColor(getVehicle(vehicleID)->getParameter().color);
181 : }
182 :
183 : double
184 1576553 : TraCI_Vehicle::getLanePosition(const std::string& vehicleID) {
185 1576553 : MSVehicle* veh = getVehicle(vehicleID);
186 1576548 : return veh->isOnRoad() ? veh->getPositionOnLane() : INVALID_DOUBLE_VALUE;
187 : }
188 :
189 : double
190 25 : TraCI_Vehicle::getLateralLanePosition(const std::string& vehicleID) {
191 25 : MSVehicle* veh = getVehicle(vehicleID);
192 25 : return veh->isOnRoad() ? veh->getLateralPositionOnLane() : INVALID_DOUBLE_VALUE;
193 : }
194 :
195 : double
196 100 : TraCI_Vehicle::getCO2Emission(const std::string& vehicleID) {
197 100 : MSVehicle* veh = getVehicle(vehicleID);
198 100 : return isVisible(veh) ? veh->getCO2Emissions() : INVALID_DOUBLE_VALUE;
199 : }
200 :
201 : double
202 20 : TraCI_Vehicle::getCOEmission(const std::string& vehicleID) {
203 20 : MSVehicle* veh = getVehicle(vehicleID);
204 20 : return isVisible(veh) ? veh->getCOEmissions() : INVALID_DOUBLE_VALUE;
205 : }
206 :
207 : double
208 20 : TraCI_Vehicle::getHCEmission(const std::string& vehicleID) {
209 20 : MSVehicle* veh = getVehicle(vehicleID);
210 20 : return isVisible(veh) ? veh->getHCEmissions() : INVALID_DOUBLE_VALUE;
211 : }
212 :
213 : double
214 20 : TraCI_Vehicle::getPMxEmission(const std::string& vehicleID) {
215 20 : MSVehicle* veh = getVehicle(vehicleID);
216 20 : return isVisible(veh) ? veh->getPMxEmissions() : INVALID_DOUBLE_VALUE;
217 : }
218 :
219 : double
220 20 : TraCI_Vehicle::getNOxEmission(const std::string& vehicleID) {
221 20 : MSVehicle* veh = getVehicle(vehicleID);
222 20 : return isVisible(veh) ? veh->getNOxEmissions() : INVALID_DOUBLE_VALUE;
223 : }
224 :
225 : double
226 20 : TraCI_Vehicle::getFuelConsumption(const std::string& vehicleID) {
227 20 : MSVehicle* veh = getVehicle(vehicleID);
228 20 : return isVisible(veh) ? veh->getFuelConsumption() : INVALID_DOUBLE_VALUE;
229 : }
230 :
231 : double
232 20 : TraCI_Vehicle::getNoiseEmission(const std::string& vehicleID) {
233 20 : MSVehicle* veh = getVehicle(vehicleID);
234 20 : return isVisible(veh) ? veh->getHarmonoise_NoiseEmissions() : INVALID_DOUBLE_VALUE;
235 : }
236 :
237 : double
238 38 : TraCI_Vehicle::getElectricityConsumption(const std::string& vehicleID) {
239 38 : MSVehicle* veh = getVehicle(vehicleID);
240 38 : return isVisible(veh) ? veh->getElectricityConsumption() : INVALID_DOUBLE_VALUE;
241 : }
242 :
243 : int
244 18 : TraCI_Vehicle::getPersonNumber(const std::string& vehicleID) {
245 18 : return getVehicle(vehicleID)->getPersonNumber();
246 : }
247 :
248 :
249 : std::pair<std::string, double>
250 305 : TraCI_Vehicle::getLeader(const std::string& vehicleID, double dist) {
251 305 : MSVehicle* veh = getVehicle(vehicleID);
252 305 : if (veh->isOnRoad()) {
253 305 : std::pair<const MSVehicle* const, double> leaderInfo = veh->getLeader(dist);
254 : return std::make_pair(
255 333 : leaderInfo.first != 0 ? leaderInfo.first->getID() : "",
256 333 : leaderInfo.second);
257 : } else {
258 0 : return std::make_pair("", -1);
259 : }
260 : }
261 :
262 :
263 : double
264 22 : TraCI_Vehicle::getWaitingTime(const std::string& vehicleID) {
265 22 : return getVehicle(vehicleID)->getWaitingSeconds();
266 : }
267 :
268 :
269 : double
270 22 : TraCI_Vehicle::getAccumulatedWaitingTime(const std::string& vehicleID) {
271 22 : return getVehicle(vehicleID)->getAccumulatedWaitingSeconds();
272 : }
273 :
274 :
275 : double
276 30 : TraCI_Vehicle::getAdaptedTraveltime(const std::string& vehicleID, const std::string& edgeID, int time) {
277 30 : MSVehicle* veh = getVehicle(vehicleID);
278 30 : MSEdge* edge = TraCI::getEdge(edgeID);
279 30 : double value = INVALID_DOUBLE_VALUE;;
280 30 : veh->getWeightsStorage().retrieveExistingTravelTime(edge, time, value);
281 30 : return value;
282 : }
283 :
284 :
285 : double
286 30 : TraCI_Vehicle::getEffort(const std::string& vehicleID, const std::string& edgeID, int time) {
287 30 : MSVehicle* veh = getVehicle(vehicleID);
288 30 : MSEdge* edge = TraCI::getEdge(edgeID);
289 30 : double value = INVALID_DOUBLE_VALUE;;
290 30 : veh->getWeightsStorage().retrieveExistingEffort(edge, time, value);
291 30 : return value;
292 : }
293 :
294 :
295 : bool
296 19 : TraCI_Vehicle::isRouteValid(const std::string& vehicleID) {
297 19 : std::string msg;
298 19 : return getVehicle(vehicleID)->hasValidRoute(msg);
299 : }
300 :
301 : std::vector<std::string>
302 95 : TraCI_Vehicle::getEdges(const std::string& vehicleID) {
303 95 : std::vector<std::string> result;
304 95 : MSVehicle* veh = getVehicle(vehicleID);
305 95 : const MSRoute& r = veh->getRoute();
306 548 : for (MSRouteIterator i = r.begin(); i != r.end(); ++i) {
307 453 : result.push_back((*i)->getID());
308 : }
309 95 : return result;
310 : }
311 :
312 :
313 : int
314 20 : TraCI_Vehicle::getSignalStates(const std::string& vehicleID) {
315 20 : return getVehicle(vehicleID)->getSignals();
316 : }
317 :
318 : std::vector<TraCIBestLanesData>
319 33 : TraCI_Vehicle::getBestLanes(const std::string& vehicleID) {
320 33 : std::vector<TraCIBestLanesData> result;
321 33 : MSVehicle* veh = getVehicle(vehicleID);
322 33 : if (veh->isOnRoad()) {
323 23 : const std::vector<MSVehicle::LaneQ>& bestLanes = veh->getBestLanes();
324 74 : for (std::vector<MSVehicle::LaneQ>::const_iterator i = bestLanes.begin(); i != bestLanes.end(); ++i) {
325 51 : TraCIBestLanesData bld;
326 51 : const MSVehicle::LaneQ& lq = *i;
327 51 : bld.laneID = lq.lane->getID();
328 51 : bld.length = lq.length;
329 51 : bld.occupation = lq.nextOccupation;
330 51 : bld.bestLaneOffset = lq.bestLaneOffset;
331 51 : bld.allowsContinuation = lq.allowsContinuation;
332 194 : for (std::vector<MSLane*>::const_iterator j = lq.bestContinuations.begin(); j != lq.bestContinuations.end(); ++j) {
333 143 : if ((*j) != 0) {
334 143 : bld.continuationLanes.push_back((*j)->getID());
335 : }
336 : }
337 51 : result.push_back(bld);
338 51 : }
339 : }
340 33 : return result;
341 : }
342 :
343 :
344 : std::vector<TraCINextTLSData>
345 3 : TraCI_Vehicle::getNextTLS(const std::string& vehicleID) {
346 3 : std::vector<TraCINextTLSData> result;
347 3 : MSVehicle* veh = getVehicle(vehicleID);
348 3 : if (veh->isOnRoad()) {
349 3 : const MSLane* lane = veh->getLane();
350 3 : const std::vector<MSLane*>& bestLaneConts = veh->getBestLanesContinuation(lane);
351 3 : double seen = veh->getLane()->getLength() - veh->getPositionOnLane();
352 3 : int view = 1;
353 3 : MSLinkCont::const_iterator link = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
354 24 : while (!lane->isLinkEnd(link)) {
355 18 : if (!lane->getEdge().isInternal()) {
356 17 : if ((*link)->isTLSControlled()) {
357 7 : TraCINextTLSData ntd;
358 7 : ntd.id = (*link)->getTLLogic()->getID();
359 7 : ntd.tlIndex = (*link)->getTLIndex();
360 7 : ntd.dist = seen;
361 7 : ntd.state = (char)(*link)->getState();
362 7 : result.push_back(ntd);
363 : }
364 : }
365 18 : lane = (*link)->getViaLaneOrLane();
366 18 : if (!lane->getEdge().isInternal()) {
367 17 : view++;
368 : }
369 18 : seen += lane->getLength();
370 18 : link = MSLane::succLinkSec(*veh, view, *lane, bestLaneConts);
371 : }
372 : }
373 3 : return result;
374 : }
375 :
376 : int
377 122 : TraCI_Vehicle::getStopState(const std::string& vehicleID) {
378 122 : MSVehicle* veh = getVehicle(vehicleID);
379 122 : int result = 0;
380 122 : if (veh->isStopped()) {
381 29 : const MSVehicle::Stop& stop = veh->getNextStop();
382 29 : result = (1 + (stop.pars.parking ? 2 : 0) +
383 29 : (stop.pars.triggered ? 4 : 0) +
384 29 : (stop.pars.containerTriggered ? 8 : 0) +
385 58 : (stop.busstop != 0 ? 16 : 0) +
386 58 : (stop.containerstop != 0 ? 32 : 0) +
387 58 : (stop.chargingStation != 0 ? 64 : 0) +
388 58 : (stop.parkingarea != 0 ? 128 : 0));
389 : }
390 122 : return result;
391 : }
392 :
393 : double
394 24 : TraCI_Vehicle::getDistance(const std::string& vehicleID) {
395 24 : MSVehicle* veh = getVehicle(vehicleID);
396 24 : if (veh->isOnRoad()) {
397 24 : double distance = veh->getRoute().getDistanceBetween(veh->getDepartPos(), veh->getPositionOnLane(), veh->getRoute().getEdges()[0], &veh->getLane()->getEdge());
398 24 : if (distance == std::numeric_limits<double>::max()) {
399 0 : return INVALID_DOUBLE_VALUE;
400 : } else {
401 24 : return distance;
402 : }
403 : } else {
404 0 : return INVALID_DOUBLE_VALUE;
405 : }
406 : }
407 :
408 :
409 : double
410 58 : TraCI_Vehicle::getDrivingDistance(const std::string& vehicleID, const std::string& edgeID, double position, int /* laneIndex */) {
411 58 : MSVehicle* veh = getVehicle(vehicleID);
412 58 : if (veh->isOnRoad()) {
413 96 : double distance = veh->getRoute().getDistanceBetween(veh->getPositionOnLane(), position,
414 144 : &veh->getLane()->getEdge(), TraCI::getEdge(edgeID));
415 48 : if (distance == std::numeric_limits<double>::max()) {
416 10 : return INVALID_DOUBLE_VALUE;
417 : }
418 38 : return distance;
419 : } else {
420 10 : return INVALID_DOUBLE_VALUE;
421 : }
422 : }
423 :
424 :
425 : double
426 21 : TraCI_Vehicle::getDrivingDistance2D(const std::string& vehicleID, double x, double y) {
427 21 : MSVehicle* veh = getVehicle(vehicleID);
428 21 : if (veh->isOnRoad()) {
429 11 : std::pair<MSLane*, double> roadPos = TraCI::convertCartesianToRoadMap(Position(x, y));
430 22 : double distance = veh->getRoute().getDistanceBetween(veh->getPositionOnLane(), roadPos.second,
431 33 : veh->getEdge(), &roadPos.first->getEdge());
432 11 : if (distance == std::numeric_limits<double>::max()) {
433 4 : return INVALID_DOUBLE_VALUE;
434 : }
435 7 : return distance;
436 : } else {
437 10 : return INVALID_DOUBLE_VALUE;
438 : }
439 : }
440 :
441 :
442 :
443 : double
444 18 : TraCI_Vehicle::getAllowedSpeed(const std::string& vehicleID) {
445 18 : MSVehicle* veh = getVehicle(vehicleID);
446 18 : if (veh->isOnRoad()) {
447 8 : return veh->getLane()->getVehicleMaxSpeed(veh);
448 : } else {
449 10 : return INVALID_DOUBLE_VALUE;
450 : }
451 : }
452 :
453 : double
454 26 : TraCI_Vehicle::getSpeedFactor(const std::string& vehicleID) {
455 26 : return getVehicle(vehicleID)->getChosenSpeedFactor();
456 : }
457 :
458 :
459 : int
460 3 : TraCI_Vehicle::getSpeedMode(const std::string& vehicleID) {
461 3 : return getVehicle(vehicleID)->getInfluencer().getSpeedMode();
462 : }
463 :
464 : int
465 0 : TraCI_Vehicle::getLanechangeMode(const std::string& vehicleID) {
466 0 : return getVehicle(vehicleID)->getInfluencer().getLanechangeMode();
467 : }
468 :
469 : int
470 0 : TraCI_Vehicle::getRoutingMode(const std::string& vehicleID) {
471 0 : return getVehicle(vehicleID)->getInfluencer().getRoutingMode();
472 : }
473 :
474 : std::string
475 19 : TraCI_Vehicle::getLine(const std::string& vehicleID) {
476 19 : return getVehicle(vehicleID)->getParameter().line;
477 : }
478 :
479 : std::vector<std::string>
480 19 : TraCI_Vehicle::getVia(const std::string& vehicleID) {
481 19 : return getVehicle(vehicleID)->getParameter().via;
482 : }
483 :
484 :
485 : std::pair<int, int>
486 108 : TraCI_Vehicle::getLaneChangeState(const std::string& vehicleID, int direction) {
487 108 : MSVehicle* veh = getVehicle(vehicleID);
488 108 : if (veh->isOnRoad()) {
489 48 : return veh->getLaneChangeModel().getSavedState(direction);
490 : } else {
491 60 : return std::make_pair((int)LCA_UNKNOWN, (int)LCA_UNKNOWN);
492 : }
493 : }
494 :
495 :
496 : std::string
497 185 : TraCI_Vehicle::getParameter(const std::string& vehicleID, const std::string& key) {
498 185 : MSVehicle* veh = getVehicle(vehicleID);
499 185 : if (StringUtils::startsWith(key, "device.")) {
500 115 : StringTokenizer tok(key, ".");
501 115 : if (tok.size() < 3) {
502 0 : throw TraCIException("Invalid device parameter '" + key + "' for vehicle '" + vehicleID + "'");
503 : }
504 : try {
505 119 : return veh->getDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2));
506 4 : } catch (InvalidArgument& e) {
507 4 : throw TraCIException("Vehicle '" + vehicleID + "' does not support device parameter '" + key + "' (" + e.what() + ").");
508 115 : }
509 70 : } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
510 54 : const std::string attrName = key.substr(16);
511 : try {
512 54 : return veh->getLaneChangeModel().getParameter(attrName);
513 0 : } catch (InvalidArgument& e) {
514 0 : throw TraCIException("Vehicle '" + vehicleID + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").");
515 54 : }
516 16 : } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
517 8 : StringTokenizer tok(key, ".");
518 8 : if (tok.size() != 3) {
519 0 : throw TraCIException("Invalid check for device. Expected format is 'has.DEVICENAME.device'");
520 : }
521 8 : return veh->hasDevice(tok.get(1)) ? "true" : "false";
522 : } else {
523 8 : return veh->getParameter().getParameter(key, "");
524 : }
525 : }
526 :
527 :
528 : const MSVehicleType&
529 1166 : TraCI_Vehicle::getVehicleType(const std::string& vehicleID) {
530 1166 : return getVehicle(vehicleID)->getVehicleType();
531 : }
532 :
533 :
534 : std::string
535 0 : TraCI_Vehicle::getEmissionClass(const std::string& vehicleID) {
536 0 : return PollutantsInterface::getName(getVehicleType(vehicleID).getEmissionClass());
537 : }
538 :
539 : std::string
540 0 : TraCI_Vehicle::getShapeClass(const std::string& vehicleID) {
541 0 : return getVehicleShapeName(getVehicleType(vehicleID).getGuiShape());
542 : }
543 :
544 :
545 : double
546 0 : TraCI_Vehicle::getLength(const std::string& vehicleID) {
547 0 : return getVehicleType(vehicleID).getLength();
548 : }
549 :
550 :
551 : double
552 0 : TraCI_Vehicle::getAccel(const std::string& vehicleID) {
553 0 : return getVehicleType(vehicleID).getLength();
554 : }
555 :
556 :
557 : double
558 0 : TraCI_Vehicle::getDecel(const std::string& vehicleID) {
559 0 : return getVehicleType(vehicleID).getCarFollowModel().getMaxDecel();
560 : }
561 :
562 :
563 0 : double TraCI_Vehicle::getEmergencyDecel(const std::string& vehicleID) {
564 0 : return getVehicleType(vehicleID).getCarFollowModel().getEmergencyDecel();
565 : }
566 0 : double TraCI_Vehicle::getApparentDecel(const std::string& vehicleID) {
567 0 : return getVehicleType(vehicleID).getCarFollowModel().getApparentDecel();
568 : }
569 0 : double TraCI_Vehicle::getActionStepLength(const std::string& vehicleID) {
570 0 : return getVehicleType(vehicleID).getActionStepLengthSecs();
571 : }
572 0 : double TraCI_Vehicle::getLastActionTime(const std::string& vehicleID) {
573 0 : return STEPS2TIME(getVehicle(vehicleID)->getLastActionTime());
574 : }
575 :
576 : double
577 0 : TraCI_Vehicle::getTau(const std::string& vehicleID) {
578 0 : return getVehicleType(vehicleID).getCarFollowModel().getHeadwayTime();
579 : }
580 :
581 :
582 : double
583 0 : TraCI_Vehicle::getImperfection(const std::string& vehicleID) {
584 0 : return getVehicleType(vehicleID).getCarFollowModel().getImperfection();
585 : }
586 :
587 :
588 : double
589 0 : TraCI_Vehicle::getSpeedDeviation(const std::string& vehicleID) {
590 0 : return getVehicleType(vehicleID).getSpeedFactor().getParameter()[1];
591 : }
592 :
593 :
594 : std::string
595 0 : TraCI_Vehicle::getVClass(const std::string& vehicleID) {
596 0 : return toString(getVehicleType(vehicleID).getVehicleClass());
597 : }
598 :
599 :
600 : double
601 0 : TraCI_Vehicle::getMinGap(const std::string& vehicleID) {
602 0 : return getVehicleType(vehicleID).getMinGap();
603 : }
604 :
605 :
606 : double
607 0 : TraCI_Vehicle::getMaxSpeed(const std::string& vehicleID) {
608 0 : return getVehicleType(vehicleID).getMaxSpeed();
609 : }
610 :
611 :
612 : double
613 0 : TraCI_Vehicle::getWidth(const std::string& vehicleID) {
614 0 : return getVehicleType(vehicleID).getWidth();
615 : }
616 :
617 :
618 : void
619 4485 : TraCI_Vehicle::setStop(const std::string& vehicleID,
620 : const std::string& edgeID,
621 : double endPos,
622 : int laneIndex,
623 : SUMOTime duration,
624 : int flags,
625 : double startPos,
626 : SUMOTime until) {
627 4485 : MSVehicle* veh = getVehicle(vehicleID);
628 : // optional stop flags
629 4485 : bool parking = false;
630 4485 : bool triggered = false;
631 4485 : bool containerTriggered = false;
632 4485 : SumoXMLTag stoppingPlaceType = SUMO_TAG_NOTHING;
633 :
634 4485 : parking = ((flags & 1) != 0);
635 4485 : triggered = ((flags & 2) != 0);
636 4485 : containerTriggered = ((flags & 4) != 0);
637 4485 : if ((flags & 8) != 0) {
638 2 : stoppingPlaceType = SUMO_TAG_BUS_STOP;
639 : }
640 4485 : if ((flags & 16) != 0) {
641 0 : stoppingPlaceType = SUMO_TAG_CONTAINER_STOP;
642 : }
643 4485 : if ((flags & 32) != 0) {
644 0 : stoppingPlaceType = SUMO_TAG_CHARGING_STATION;
645 : }
646 4485 : if ((flags & 64) != 0) {
647 2 : stoppingPlaceType = SUMO_TAG_PARKING_AREA;
648 : }
649 :
650 4485 : std::string error;
651 4485 : if (stoppingPlaceType != SUMO_TAG_NOTHING) {
652 : // Forward command to vehicle
653 4 : if (!veh->addTraciStopAtStoppingPlace(edgeID, duration, until, parking, triggered, containerTriggered, stoppingPlaceType, error)) {
654 0 : throw TraCIException(error);
655 : }
656 : } else {
657 : // check
658 4481 : if (startPos < 0) {
659 0 : throw TraCIException("Position on lane must not be negative.");
660 : }
661 4481 : if (endPos < startPos) {
662 0 : throw TraCIException("End position on lane must be after start position.");
663 : }
664 : // get the actual lane that is referenced by laneIndex
665 4481 : MSEdge* road = MSEdge::dictionary(edgeID);
666 4481 : if (road == 0) {
667 0 : throw TraCIException("Unable to retrieve road with given id.");
668 : }
669 4481 : const std::vector<MSLane*>& allLanes = road->getLanes();
670 4481 : if ((laneIndex < 0) || laneIndex >= (int)(allLanes.size())) {
671 0 : throw TraCIException("No lane with index '" + toString(laneIndex) + "' on road '" + edgeID + "'.");
672 : }
673 : // Forward command to vehicle
674 4481 : if (!veh->addTraciStop(allLanes[laneIndex], startPos, endPos, duration, until, parking, triggered, containerTriggered, error)) {
675 1 : throw TraCIException(error);
676 : }
677 4485 : }
678 4484 : }
679 :
680 :
681 : void
682 4 : TraCI_Vehicle::resume(const std::string& vehicleID) {
683 4 : MSVehicle* veh = getVehicle(vehicleID);
684 4 : if (!veh->hasStops()) {
685 0 : throw TraCIException("Failed to resume vehicle '" + veh->getID() + "', it has no stops.");
686 : }
687 4 : if (!veh->resumeFromStopping()) {
688 0 : MSVehicle::Stop& sto = veh->getNextStop();
689 0 : std::ostringstream strs;
690 0 : strs << "reached: " << sto.reached;
691 0 : strs << ", duration:" << sto.duration;
692 0 : strs << ", edge:" << (*sto.edge)->getID();
693 0 : strs << ", startPos: " << sto.pars.startPos;
694 0 : std::string posStr = strs.str();
695 0 : throw TraCIException("Failed to resume from stoppingfor vehicle '" + veh->getID() + "', " + posStr);
696 : }
697 4 : }
698 :
699 :
700 : void
701 1927 : TraCI_Vehicle::changeTarget(const std::string& vehicleID, const std::string& edgeID) {
702 1927 : MSVehicle* veh = getVehicle(vehicleID);
703 1927 : const MSEdge* destEdge = MSEdge::dictionary(edgeID);
704 1927 : const bool onInit = isOnInit(vehicleID);
705 1927 : if (destEdge == 0) {
706 1 : throw TraCIException("Can not retrieve road with ID " + edgeID);
707 : }
708 : // build a new route between the vehicle's current edge and destination edge
709 1926 : ConstMSEdgeVector newRoute;
710 1926 : const MSEdge* currentEdge = veh->getRerouteOrigin();
711 3852 : MSNet::getInstance()->getRouterTT().compute(
712 1926 : currentEdge, destEdge, (const MSVehicle * const) veh, MSNet::getInstance()->getCurrentTimeStep(), newRoute);
713 : // replace the vehicle's route by the new one
714 1926 : if (!veh->replaceRouteEdges(newRoute, onInit)) {
715 1 : throw TraCIException("Route replacement failed for " + veh->getID());
716 : }
717 : // route again to ensure usage of via/stops
718 : try {
719 1925 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterTT(), onInit);
720 0 : } catch (ProcessError& e) {
721 0 : throw TraCIException(e.what());
722 1926 : }
723 1925 : }
724 :
725 :
726 : void
727 11 : TraCI_Vehicle::changeLane(const std::string& vehicleID, int laneIndex, SUMOTime duration) {
728 11 : std::vector<std::pair<SUMOTime, int> > laneTimeLine;
729 11 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), laneIndex));
730 11 : laneTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + duration, laneIndex));
731 11 : getVehicle(vehicleID)->getInfluencer().setLaneTimeLine(laneTimeLine);
732 11 : }
733 :
734 :
735 : void
736 2 : TraCI_Vehicle::changeSublane(const std::string& vehicleID, double latDist) {
737 2 : getVehicle(vehicleID)->getInfluencer().setSublaneChange(latDist);
738 2 : }
739 :
740 :
741 : void
742 0 : TraCI_Vehicle::add(const std::string& vehicleID,
743 : const std::string& routeID,
744 : const std::string& typeID,
745 : std::string depart,
746 : const std::string& departLane,
747 : const std::string& departPos,
748 : const std::string& departSpeed,
749 : const std::string& arrivalLane,
750 : const std::string& arrivalPos,
751 : const std::string& arrivalSpeed,
752 : const std::string& fromTaz,
753 : const std::string& toTaz,
754 : const std::string& line,
755 : int personCapacity,
756 : int personNumber) {
757 0 : MSVehicle* veh = getVehicle(vehicleID);
758 0 : if (veh != 0) {
759 0 : throw TraCIException("The vehicle " + vehicleID + " to add already exists.");
760 : }
761 0 : }
762 :
763 :
764 : void
765 0 : TraCI_Vehicle::moveToXY(const std::string& vehicleID, const std::string& edgeID, const int lane, const double x, const double y, const double angle, const int keepRoute) {
766 0 : getVehicle(vehicleID);
767 0 : }
768 :
769 : void
770 16 : TraCI_Vehicle::slowDown(const std::string& vehicleID, double speed, SUMOTime duration) {
771 16 : MSVehicle* veh = getVehicle(vehicleID);
772 16 : std::vector<std::pair<SUMOTime, double> > speedTimeLine;
773 16 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep(), veh->getSpeed()));
774 16 : speedTimeLine.push_back(std::make_pair(MSNet::getInstance()->getCurrentTimeStep() + duration, speed));
775 16 : veh->getInfluencer().setSpeedTimeLine(speedTimeLine);
776 16 : }
777 :
778 : void
779 0 : TraCI_Vehicle::setSpeed(const std::string& vehicleID, double speed) {
780 0 : getVehicle(vehicleID);
781 0 : }
782 :
783 : void
784 5 : TraCI_Vehicle::setType(const std::string& vehicleID, const std::string& typeID) {
785 5 : MSVehicleType* vehicleType = MSNet::getInstance()->getVehicleControl().getVType(typeID);
786 5 : if (vehicleType == 0) {
787 0 : throw TraCIException("Vehicle type '" + vehicleID + "' is not known");
788 : }
789 5 : getVehicle(vehicleID)->replaceVehicleType(vehicleType);
790 5 : }
791 :
792 : void
793 8 : TraCI_Vehicle::setRouteID(const std::string& vehicleID, const std::string& routeID) {
794 8 : MSVehicle* veh = getVehicle(vehicleID);
795 8 : const MSRoute* r = MSRoute::dictionary(routeID);
796 8 : if (r == 0) {
797 1 : throw TraCIException("The route '" + routeID + "' is not known.");
798 : }
799 7 : std::string msg;
800 7 : if (!veh->hasValidRoute(msg, r)) {
801 1 : WRITE_WARNING("Invalid route replacement for vehicle '" + veh->getID() + "'. " + msg);
802 1 : if (MSGlobals::gCheckRoutes) {
803 1 : throw TraCIException("Route replacement failed for " + veh->getID());
804 : }
805 : }
806 :
807 6 : if (!veh->replaceRoute(r, veh->getLane() == 0)) {
808 1 : throw TraCIException("Route replacement failed for " + veh->getID());
809 7 : }
810 5 : }
811 :
812 :
813 : void
814 11 : TraCI_Vehicle::setRoute(const std::string& vehicleID, const std::vector<std::string>& edgeIDs) {
815 11 : MSVehicle* veh = getVehicle(vehicleID);
816 11 : ConstMSEdgeVector edges;
817 : try {
818 15 : MSEdge::parseEdgesList(edgeIDs, edges, "<unknown>");
819 4 : } catch (ProcessError& e) {
820 4 : throw TraCIException("Invalid edge list for vehicle '" + veh->getID() + "' (" + e.what() + ")");
821 : }
822 7 : if (!veh->replaceRouteEdges(edges, veh->getLane() == 0, true)) {
823 3 : throw TraCIException("Route replacement failed for " + veh->getID());
824 11 : }
825 4 : }
826 :
827 : void
828 10 : TraCI_Vehicle::setAdaptedTraveltime(const std::string& vehicleID, const std::string& edgeID,
829 : double time, SUMOTime begTime, SUMOTime endTime) {
830 10 : MSVehicle* veh = getVehicle(vehicleID);
831 10 : MSEdge* edge = MSEdge::dictionary(edgeID);
832 10 : if (edge == 0) {
833 0 : throw TraCIException("Referended edge '" + edgeID + "' is not known.");
834 : }
835 10 : if (time != INVALID_DOUBLE_VALUE) {
836 : // add time
837 8 : if (begTime == 0 && endTime == SUMOTime_MAX) {
838 : // clean up old values before setting whole range
839 4 : while (veh->getWeightsStorage().knowsTravelTime(edge)) {
840 0 : veh->getWeightsStorage().removeTravelTime(edge);
841 : }
842 : }
843 8 : veh->getWeightsStorage().addTravelTime(edge, begTime, endTime, time);
844 : } else {
845 : // remove time
846 6 : while (veh->getWeightsStorage().knowsTravelTime(edge)) {
847 2 : veh->getWeightsStorage().removeTravelTime(edge);
848 : }
849 : }
850 10 : }
851 :
852 :
853 : void
854 8 : TraCI_Vehicle::setEffort(const std::string& vehicleID, const std::string& edgeID,
855 : double effort, SUMOTime begTime, SUMOTime endTime) {
856 8 : MSVehicle* veh = getVehicle(vehicleID);
857 8 : MSEdge* edge = MSEdge::dictionary(edgeID);
858 8 : if (edge == 0) {
859 0 : throw TraCIException("Referended edge '" + edgeID + "' is not known.");
860 : }
861 8 : if (effort != INVALID_DOUBLE_VALUE) {
862 : // add effort
863 6 : if (begTime == 0 && endTime == SUMOTime_MAX) {
864 : // clean up old values before setting whole range
865 4 : while (veh->getWeightsStorage().knowsEffort(edge)) {
866 0 : veh->getWeightsStorage().removeEffort(edge);
867 : }
868 : }
869 6 : veh->getWeightsStorage().addEffort(edge, begTime, endTime, effort);
870 : } else {
871 : // remove effort
872 6 : while (veh->getWeightsStorage().knowsEffort(edge)) {
873 2 : veh->getWeightsStorage().removeEffort(edge);
874 : }
875 : }
876 8 : }
877 :
878 :
879 : void
880 11 : TraCI_Vehicle::rerouteTraveltime(const std::string& vehicleID) {
881 11 : MSVehicle* veh = getVehicle(vehicleID);
882 11 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterTT(), isOnInit(vehicleID));
883 11 : }
884 :
885 :
886 : void
887 4 : TraCI_Vehicle::rerouteEffort(const std::string& vehicleID) {
888 4 : MSVehicle* veh = getVehicle(vehicleID);
889 4 : veh->reroute(MSNet::getInstance()->getCurrentTimeStep(), MSNet::getInstance()->getRouterEffort(), isOnInit(vehicleID));
890 4 : }
891 :
892 :
893 : void
894 6 : TraCI_Vehicle::setSignals(const std::string& vehicleID, int signals) {
895 6 : MSVehicle* veh = getVehicle(vehicleID);
896 : // set influencer to make the change persistent
897 6 : veh->getInfluencer().setSignals(signals);
898 : // set them now so that getSignals returns the correct value
899 6 : veh->switchOffSignal(0x0fffffff);
900 6 : if (signals >= 0) {
901 5 : veh->switchOnSignal(signals);
902 : }
903 6 : }
904 :
905 :
906 : void
907 18 : TraCI_Vehicle::moveTo(const std::string& vehicleID, const std::string& laneID, double position) {
908 18 : MSVehicle* veh = getVehicle(vehicleID);
909 18 : MSLane* l = MSLane::dictionary(laneID);
910 18 : if (l == 0) {
911 1 : throw TraCIException("Unknown lane '" + laneID + "'.");
912 : }
913 17 : MSEdge& destinationEdge = l->getEdge();
914 17 : if (!veh->willPass(&destinationEdge)) {
915 1 : throw TraCIException("Vehicle '" + laneID + "' may be set onto an edge to pass only.");
916 : }
917 16 : veh->onRemovalFromNet(MSMoveReminder::NOTIFICATION_TELEPORT);
918 16 : if (veh->getLane() != 0) {
919 9 : veh->getLane()->removeVehicle(veh, MSMoveReminder::NOTIFICATION_TELEPORT);
920 : } else {
921 7 : veh->setTentativeLaneAndPosition(l, position);
922 : }
923 53 : while (veh->getEdge() != &destinationEdge) {
924 21 : const MSEdge* nextEdge = veh->succEdge(1);
925 : // let the vehicle move to the next edge
926 21 : if (veh->enterLaneAtMove(nextEdge->getLanes()[0], true)) {
927 0 : MSNet::getInstance()->getVehicleControl().scheduleVehicleRemoval(veh);
928 0 : continue;
929 : }
930 : }
931 16 : if (!veh->isOnRoad()) {
932 16 : MSNet::getInstance()->getInsertionControl().alreadyDeparted(veh);
933 :
934 : }
935 : l->forceVehicleInsertion(veh, position,
936 16 : veh->hasDeparted() ? MSMoveReminder::NOTIFICATION_TELEPORT : MSMoveReminder::NOTIFICATION_DEPARTED);
937 16 : }
938 :
939 :
940 : void
941 0 : TraCI_Vehicle::setMaxSpeed(const std::string& vehicleID, double speed) {
942 0 : getVehicle(vehicleID)->getSingularType().setMaxSpeed(speed);
943 0 : }
944 :
945 : void
946 8 : TraCI_Vehicle::setActionStepLength(const std::string& vehicleID, double actionStepLength, bool resetActionOffset) {
947 8 : if (actionStepLength < 0.0) {
948 0 : WRITE_ERROR("Invalid action step length (<0). Ignoring command setActionStepLength().");
949 0 : return;
950 : }
951 8 : MSVehicle* veh = getVehicle(vehicleID);
952 8 : if(actionStepLength==0.) {
953 0 : veh->resetActionOffset();
954 0 : return;
955 : }
956 8 : SUMOTime actionStepLengthMillisecs = SUMOVehicleParserHelper::processActionStepLength(actionStepLength);
957 8 : SUMOTime previousActionStepLength = veh->getActionStepLength();
958 8 : veh->getSingularType().setActionStepLength(actionStepLengthMillisecs, resetActionOffset);
959 8 : if(resetActionOffset) {
960 6 : veh->resetActionOffset();
961 : } else {
962 2 : veh->updateActionOffset(previousActionStepLength, actionStepLengthMillisecs);
963 : }
964 : }
965 :
966 : void
967 0 : TraCI_Vehicle::remove(const std::string& vehicleID, char reason) {
968 0 : getVehicle(vehicleID);
969 0 : }
970 :
971 :
972 : void
973 0 : TraCI_Vehicle::setColor(const std::string& vehicleID, const TraCIColor& col) {
974 0 : const SUMOVehicleParameter& p = getVehicle(vehicleID)->getParameter();
975 0 : p.color.set(col.r, col.g, col.b, col.a);
976 0 : p.parametersSet |= VEHPARS_COLOR_SET;
977 0 : }
978 :
979 :
980 : void
981 0 : TraCI_Vehicle::setLine(const std::string& vehicleID, const std::string& line) {
982 0 : getVehicle(vehicleID)->getParameter().line = line;
983 0 : }
984 :
985 : void
986 0 : TraCI_Vehicle::setVia(const std::string& vehicleID, const std::vector<std::string>& via) {
987 0 : getVehicle(vehicleID);
988 0 : }
989 :
990 : void
991 0 : TraCI_Vehicle::setShapeClass(const std::string& vehicleID, const std::string& clazz) {
992 0 : getVehicle(vehicleID)->getSingularType().setShape(getVehicleShapeID(clazz));
993 0 : }
994 :
995 : void
996 0 : TraCI_Vehicle::setEmissionClass(const std::string& vehicleID, const std::string& clazz) {
997 0 : getVehicle(vehicleID);
998 0 : }
999 :
1000 :
1001 : void
1002 16 : TraCI_Vehicle::setParameter(const std::string& vehicleID, const std::string& key, const std::string& value) {
1003 16 : MSVehicle* veh = getVehicle(vehicleID);
1004 16 : if (StringUtils::startsWith(key, "device.")) {
1005 6 : StringTokenizer tok(key, ".");
1006 6 : if (tok.size() < 3) {
1007 0 : throw TraCIException("Invalid device parameter '" + key + "' for vehicle '" + vehicleID + "'");
1008 : }
1009 : try {
1010 6 : veh->setDeviceParameter(tok.get(1), key.substr(tok.get(0).size() + tok.get(1).size() + 2), value);
1011 0 : } catch (InvalidArgument& e) {
1012 0 : throw TraCIException("Vehicle '" + vehicleID + "' does not support device parameter '" + key + "' (" + e.what() + ").");
1013 6 : }
1014 10 : } else if (StringUtils::startsWith(key, "laneChangeModel.")) {
1015 2 : const std::string attrName = key.substr(16);
1016 : try {
1017 2 : veh->getLaneChangeModel().setParameter(attrName, value);
1018 0 : } catch (InvalidArgument& e) {
1019 0 : throw TraCIException("Vehicle '" + vehicleID + "' does not support laneChangeModel parameter '" + key + "' (" + e.what() + ").");
1020 2 : }
1021 8 : } else if (StringUtils::startsWith(key, "has.") && StringUtils::endsWith(key, ".device")) {
1022 2 : StringTokenizer tok(key, ".");
1023 2 : if (tok.size() != 3) {
1024 0 : throw TraCIException("Invalid request for device status change. Expected format is 'has.DEVICENAME.device'");
1025 : }
1026 4 : const std::string deviceName = tok.get(1);
1027 : bool create;
1028 : try {
1029 2 : create = TplConvert::_2bool(value.c_str());
1030 0 : } catch (BoolFormatException) {
1031 0 : throw TraCIException("Changing device status requires a 'true' or 'false'");
1032 : }
1033 2 : if (!create) {
1034 0 : throw TraCIException("Device removal is not supported for device of type '" + deviceName + "'");
1035 : }
1036 : try {
1037 2 : veh->createDevice(deviceName);
1038 0 : } catch (InvalidArgument& e) {
1039 0 : throw TraCIException("Cannot create vehicle device (" + std::string(e.what()) + ").");
1040 2 : }
1041 : } else {
1042 6 : ((SUMOVehicleParameter&) veh->getParameter()).setParameter(key, value);
1043 : }
1044 43570 : }
1045 :
1046 :
1047 : /****************************************************************************/
|