Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2017-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file VehicleType.cpp
15 : /// @author Gregor Laemmel
16 : /// @date 04.04.2017
17 : ///
18 : // C++ TraCI client API implementation
19 : /****************************************************************************/
20 : #include <config.h>
21 :
22 : #include <microsim/MSNet.h>
23 : #include <microsim/MSVehicleControl.h>
24 : #include <microsim/MSVehicleType.h>
25 : #include <libsumo/TraCIConstants.h>
26 : #include <utils/emissions/PollutantsInterface.h>
27 : #include <utils/vehicle/SUMOVehicleParserHelper.h>
28 : #include "Helper.h"
29 : #include "VehicleType.h"
30 :
31 :
32 : namespace libsumo {
33 : // ===========================================================================
34 : // static member initializations
35 : // ===========================================================================
36 : SubscriptionResults VehicleType::mySubscriptionResults;
37 : ContextSubscriptionResults VehicleType::myContextSubscriptionResults;
38 :
39 :
40 : // ===========================================================================
41 : // static member definitions
42 : // ===========================================================================
43 : std::vector<std::string>
44 294 : VehicleType::getIDList() {
45 : std::vector<std::string> ids;
46 294 : MSNet::getInstance()->getVehicleControl().insertVTypeIDs(ids);
47 292 : return ids;
48 2 : }
49 :
50 :
51 : int
52 12 : VehicleType::getIDCount() {
53 12 : return (int)getIDList().size();
54 : }
55 :
56 :
57 : double
58 342 : VehicleType::getLength(const std::string& typeID) {
59 684 : return getVType(typeID)->getLength();
60 : }
61 :
62 :
63 : double
64 86 : VehicleType::getMaxSpeed(const std::string& typeID) {
65 172 : return getVType(typeID)->getMaxSpeed();
66 : }
67 :
68 :
69 : double
70 71 : VehicleType::getActionStepLength(const std::string& typeID) {
71 142 : return getVType(typeID)->getActionStepLengthSecs();
72 : }
73 :
74 :
75 : double
76 110 : VehicleType::getSpeedFactor(const std::string& typeID) {
77 110 : return getVType(typeID)->getSpeedFactor().getParameter()[0];
78 : }
79 :
80 :
81 : double
82 55 : VehicleType::getSpeedDeviation(const std::string& typeID) {
83 55 : return getVType(typeID)->getSpeedFactor().getParameter()[1];
84 : }
85 :
86 :
87 : double
88 750 : VehicleType::getAccel(const std::string& typeID) {
89 1498 : return getVType(typeID)->getCarFollowModel().getMaxAccel();
90 : }
91 :
92 :
93 : double
94 743 : VehicleType::getDecel(const std::string& typeID) {
95 1486 : return getVType(typeID)->getCarFollowModel().getMaxDecel();
96 : }
97 :
98 :
99 : double
100 645 : VehicleType::getEmergencyDecel(const std::string& typeID) {
101 1290 : return getVType(typeID)->getCarFollowModel().getEmergencyDecel();
102 : }
103 :
104 :
105 : double
106 74 : VehicleType::getApparentDecel(const std::string& typeID) {
107 148 : return getVType(typeID)->getCarFollowModel().getApparentDecel();
108 : }
109 :
110 :
111 : double
112 85 : VehicleType::getImperfection(const std::string& typeID) {
113 170 : return getVType(typeID)->getCarFollowModel().getImperfection();
114 : }
115 :
116 :
117 : double
118 380 : VehicleType::getTau(const std::string& typeID) {
119 760 : return getVType(typeID)->getCarFollowModel().getHeadwayTime();
120 : }
121 :
122 :
123 : std::string
124 569 : VehicleType::getVehicleClass(const std::string& typeID) {
125 1138 : return toString(getVType(typeID)->getVehicleClass());
126 : }
127 :
128 :
129 : std::string
130 137 : VehicleType::getEmissionClass(const std::string& typeID) {
131 274 : return PollutantsInterface::getName(getVType(typeID)->getEmissionClass());
132 : }
133 :
134 :
135 : std::string
136 60 : VehicleType::getShapeClass(const std::string& typeID) {
137 120 : return getVehicleShapeName(getVType(typeID)->getGuiShape());
138 : }
139 :
140 :
141 : double
142 520 : VehicleType::getMinGap(const std::string& typeID) {
143 1040 : return getVType(typeID)->getMinGap();
144 : }
145 :
146 :
147 : double
148 80 : VehicleType::getWidth(const std::string& typeID) {
149 160 : return getVType(typeID)->getWidth();
150 : }
151 :
152 :
153 : double
154 52 : VehicleType::getHeight(const std::string& typeID) {
155 104 : return getVType(typeID)->getHeight();
156 : }
157 :
158 :
159 : double
160 50 : VehicleType::getMass(const std::string& typeID) {
161 100 : return getVType(typeID)->getMass();
162 : }
163 :
164 :
165 : TraCIColor
166 12 : VehicleType::getColor(const std::string& typeID) {
167 24 : return Helper::makeTraCIColor(getVType(typeID)->getColor());
168 : }
169 :
170 :
171 : double
172 11 : VehicleType::getMinGapLat(const std::string& typeID) {
173 22 : return getVType(typeID)->getMinGapLat();
174 : }
175 :
176 :
177 : double
178 56 : VehicleType::getMaxSpeedLat(const std::string& typeID) {
179 112 : return getVType(typeID)->getMaxSpeedLat();
180 : }
181 :
182 :
183 : std::string
184 56 : VehicleType::getLateralAlignment(const std::string& typeID) {
185 56 : if (getVType(typeID)->getPreferredLateralAlignment() != LatAlignmentDefinition::GIVEN) {
186 112 : return toString(getVType(typeID)->getPreferredLateralAlignment());
187 : } else {
188 0 : return toString(getVType(typeID)->getPreferredLateralAlignmentOffset());
189 : }
190 : }
191 :
192 :
193 : std::string
194 107 : VehicleType::getParameter(const std::string& typeID, const std::string& key) {
195 214 : if (StringUtils::startsWith(key, "junctionModel.")) {
196 10 : const std::string attrName = key.substr(14);
197 10 : if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
198 0 : throw TraCIException("Invalid junctionModel parameter '" + key + "' for type '" + typeID + "'");
199 : }
200 10 : SumoXMLAttr attr = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attrName);
201 : if (SUMOVTypeParameter::AllowedJMAttrs.count(attr) == 0) {
202 0 : throw TraCIException("Invalid junctionModel parameter '" + key + "' for type '" + typeID + "'");
203 : }
204 20 : if (getVType(typeID)->getParameter().jmParameter.count(attr) != 0) {
205 10 : return getVType(typeID)->getParameter().jmParameter.find(attr)->second;
206 : } else {
207 5 : return "";
208 : }
209 : } else {
210 194 : return getVType(typeID)->getParameter().getParameter(key, "");
211 : }
212 : }
213 :
214 46 : LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(VehicleType)
215 :
216 : int
217 6 : VehicleType::getPersonCapacity(const std::string& typeID) {
218 12 : return getVType(typeID)->getPersonCapacity();
219 : }
220 :
221 : double
222 5 : VehicleType::getScale(const std::string& typeID) {
223 5 : return getVType(typeID)->getParameter().scale;
224 : }
225 :
226 : double
227 16 : VehicleType::getBoardingDuration(const std::string& typeID) {
228 16 : return STEPS2TIME(getVType(typeID)->getBoardingDuration(true));
229 : }
230 :
231 : double
232 10 : VehicleType::getImpatience(const std::string& typeID) {
233 20 : return getVType(typeID)->getImpatience();
234 : }
235 :
236 : void
237 80 : VehicleType::setLength(const std::string& typeID, double length) {
238 80 : getVType(typeID)->setLength(length);
239 80 : }
240 :
241 :
242 : void
243 40 : VehicleType::setMaxSpeed(const std::string& typeID, double speed) {
244 40 : getVType(typeID)->setMaxSpeed(speed);
245 40 : }
246 :
247 :
248 : void
249 13 : VehicleType::setActionStepLength(const std::string& typeID, double actionStepLength, bool resetActionOffset) {
250 13 : getVType(typeID)->setActionStepLength(SUMOVehicleParserHelper::processActionStepLength(actionStepLength), resetActionOffset);
251 13 : }
252 :
253 :
254 : void
255 10 : VehicleType::setBoardingDuration(const std::string& typeID, double boardingDuration) {
256 : try {
257 10 : checkTimeBounds(boardingDuration);
258 0 : } catch (ProcessError&) {
259 0 : throw TraCIException("BoardingDuration parameter exceeds the time value range.");
260 0 : }
261 10 : getVType(typeID)->setBoardingDuration(TIME2STEPS(boardingDuration), true);
262 10 : }
263 :
264 :
265 : void
266 5 : VehicleType::setImpatience(const std::string& typeID, double impatience) {
267 5 : getVType(typeID)->setImpatience(impatience);
268 5 : }
269 :
270 :
271 : void
272 14 : VehicleType::setVehicleClass(const std::string& typeID, const std::string& clazz) {
273 14 : getVType(typeID)->setVClass(getVehicleClassID(clazz));
274 14 : }
275 :
276 :
277 : void
278 9 : VehicleType::setSpeedFactor(const std::string& typeID, double factor) {
279 9 : getVType(typeID)->setSpeedFactor(factor);
280 9 : }
281 :
282 :
283 : void
284 5 : VehicleType::setSpeedDeviation(const std::string& typeID, double deviation) {
285 5 : getVType(typeID)->setSpeedDeviation(deviation);
286 5 : }
287 :
288 :
289 : void
290 18 : VehicleType::setEmissionClass(const std::string& typeID, const std::string& clazz) {
291 18 : getVType(typeID)->setEmissionClass(PollutantsInterface::getClassByName(clazz));
292 18 : }
293 :
294 :
295 : void
296 12 : VehicleType::setShapeClass(const std::string& typeID, const std::string& shapeClass) {
297 12 : getVType(typeID)->setShape(getVehicleShapeID(shapeClass));
298 12 : }
299 :
300 :
301 : void
302 23 : VehicleType::setWidth(const std::string& typeID, double width) {
303 23 : getVType(typeID)->setWidth(width);
304 23 : }
305 :
306 :
307 : void
308 15 : VehicleType::setHeight(const std::string& typeID, double height) {
309 15 : getVType(typeID)->setHeight(height);
310 15 : }
311 :
312 :
313 : void
314 10 : VehicleType::setMass(const std::string& typeID, double mass) {
315 10 : getVType(typeID)->setMass(mass);
316 10 : }
317 :
318 :
319 : void
320 13 : VehicleType::setMinGap(const std::string& typeID, double minGap) {
321 13 : getVType(typeID)->setMinGap(minGap);
322 13 : }
323 :
324 :
325 : void
326 30 : VehicleType::setAccel(const std::string& typeID, double accel) {
327 30 : getVType(typeID)->setAccel(accel);
328 30 : }
329 :
330 :
331 : void
332 23 : VehicleType::setDecel(const std::string& typeID, double decel) {
333 23 : MSVehicleType* v = getVType(typeID);
334 23 : v->setDecel(decel);
335 : // automatically raise emergencyDecel to ensure it is at least as high as decel
336 23 : if (decel > v->getCarFollowModel().getEmergencyDecel()) {
337 : if (v->getParameter().cfParameter.count(SUMO_ATTR_EMERGENCYDECEL) > 0) {
338 : // notify user only if emergencyDecel was previously specified
339 27 : WRITE_WARNINGF(TL("Automatically setting emergencyDecel to % for vType '%' to match decel."), toString(decel), typeID);
340 : }
341 10 : v->setEmergencyDecel(decel);
342 : }
343 23 : }
344 :
345 :
346 : void
347 32 : VehicleType::setEmergencyDecel(const std::string& typeID, double decel) {
348 32 : MSVehicleType* v = getVType(typeID);
349 32 : v->setEmergencyDecel(decel);
350 32 : if (decel < v->getCarFollowModel().getMaxDecel()) {
351 18 : WRITE_WARNINGF(TL("New value of emergencyDecel (%) is lower than decel (%)"), toString(decel), toString(v->getCarFollowModel().getMaxDecel()));
352 : }
353 32 : }
354 :
355 :
356 : void
357 18 : VehicleType::setApparentDecel(const std::string& typeID, double decel) {
358 18 : getVType(typeID)->setApparentDecel(decel);
359 18 : }
360 :
361 :
362 : void
363 25 : VehicleType::setImperfection(const std::string& typeID, double imperfection) {
364 25 : getVType(typeID)->setImperfection(imperfection);
365 25 : }
366 :
367 :
368 : void
369 18 : VehicleType::setTau(const std::string& typeID, double tau) {
370 18 : getVType(typeID)->setTau(tau);
371 18 : }
372 :
373 :
374 : void
375 5 : VehicleType::setColor(const std::string& typeID, const TraCIColor& c) {
376 5 : getVType(typeID)->setColor(Helper::makeRGBColor(c));
377 5 : }
378 :
379 :
380 : void
381 6 : VehicleType::setMinGapLat(const std::string& typeID, double minGapLat) {
382 6 : getVType(typeID)->setMinGapLat(minGapLat);
383 6 : }
384 :
385 :
386 : void
387 11 : VehicleType::setMaxSpeedLat(const std::string& typeID, double speed) {
388 11 : getVType(typeID)->setMaxSpeedLat(speed);
389 11 : }
390 :
391 :
392 : void
393 11 : VehicleType::setLateralAlignment(const std::string& typeID, const std::string& latAlignment) {
394 : double lao;
395 : LatAlignmentDefinition lad;
396 11 : if (SUMOVTypeParameter::parseLatAlignment(latAlignment, lao, lad)) {
397 11 : getVType(typeID)->setPreferredLateralAlignment(lad, lao);
398 : } else {
399 0 : throw TraCIException("Unknown value '" + latAlignment + "' when setting latAlignment for vType '" + typeID + "';\n must be one of (\"right\", \"center\", \"arbitrary\", \"nice\", \"compact\", \"left\" or a float)");
400 : }
401 11 : }
402 :
403 : void
404 5 : VehicleType::setScale(const std::string& typeID, double value) {
405 5 : getVType(typeID)->setScale(value);
406 5 : }
407 :
408 : void
409 6 : VehicleType::copy(const std::string& origTypeID, const std::string& newTypeID) {
410 6 : getVType(origTypeID)->duplicateType(newTypeID, true);
411 6 : }
412 :
413 :
414 : void
415 78 : VehicleType::setParameter(const std::string& typeID, const std::string& name, const std::string& value) {
416 156 : if (StringUtils::startsWith(name, "junctionModel.")) {
417 20 : const std::string attrName = name.substr(14);
418 20 : if (!SUMOXMLDefinitions::Attrs.hasString(attrName)) {
419 10 : throw TraCIException("Invalid junctionModel parameter '" + name + "' for type '" + typeID + "'");
420 : }
421 15 : SumoXMLAttr attr = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attrName);
422 : if (SUMOVTypeParameter::AllowedJMAttrs.count(attr) == 0) {
423 10 : throw TraCIException("Invalid junctionModel parameter '" + name + "' for type '" + typeID + "'");
424 : }
425 : try {
426 10 : StringUtils::toDouble(value); // check number format
427 10 : ((SUMOVTypeParameter&)getVType(typeID)->getParameter()).jmParameter[attr] = value;
428 5 : } catch (NumberFormatException&) {
429 10 : throw TraCIException("Invalid junctionModel parameter value '" + value + "' for type '" + typeID + " (should be numeric)'");
430 5 : }
431 : } else {
432 116 : ((SUMOVTypeParameter&)getVType(typeID)->getParameter()).setParameter(name, value);
433 : }
434 63 : }
435 :
436 :
437 270 : LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(VehicleType, VEHICLETYPE)
438 :
439 :
440 : MSVehicleType*
441 5669 : VehicleType::getVType(std::string id) {
442 5669 : MSVehicleType* t = MSNet::getInstance()->getVehicleControl().getVType(id);
443 5669 : if (t == nullptr) {
444 4 : throw TraCIException("Vehicle type '" + id + "' is not known");
445 : }
446 5667 : return t;
447 : }
448 :
449 :
450 : std::shared_ptr<VariableWrapper>
451 266 : VehicleType::makeWrapper() {
452 266 : return std::make_shared<Helper::SubscriptionWrapper>(handleVariable, mySubscriptionResults, myContextSubscriptionResults);
453 : }
454 :
455 :
456 : bool
457 3753 : VehicleType::handleVariable(const std::string& objID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
458 3753 : return handleVariableWithID(objID, objID, variable, wrapper, paramData);
459 : }
460 :
461 :
462 : bool
463 23537 : VehicleType::handleVariableWithID(const std::string& objID, const std::string& typeID, const int variable, VariableWrapper* wrapper, tcpip::Storage* paramData) {
464 23537 : switch (variable) {
465 162 : case TRACI_ID_LIST:
466 162 : return wrapper->wrapStringList(objID, variable, getIDList());
467 8 : case ID_COUNT:
468 8 : return wrapper->wrapInt(objID, variable, getIDCount());
469 245 : case VAR_LENGTH:
470 245 : return wrapper->wrapDouble(objID, variable, getLength(typeID));
471 50 : case VAR_HEIGHT:
472 50 : return wrapper->wrapDouble(objID, variable, getHeight(typeID));
473 48 : case VAR_MASS:
474 48 : return wrapper->wrapDouble(objID, variable, getMass(typeID));
475 405 : case VAR_MINGAP:
476 405 : return wrapper->wrapDouble(objID, variable, getMinGap(typeID));
477 76 : case VAR_MAXSPEED:
478 76 : return wrapper->wrapDouble(objID, variable, getMaxSpeed(typeID));
479 740 : case VAR_ACCEL:
480 740 : return wrapper->wrapDouble(objID, variable, getAccel(typeID));
481 628 : case VAR_DECEL:
482 628 : return wrapper->wrapDouble(objID, variable, getDecel(typeID));
483 439 : case VAR_EMERGENCY_DECEL:
484 439 : return wrapper->wrapDouble(objID, variable, getEmergencyDecel(typeID));
485 68 : case VAR_APPARENT_DECEL:
486 68 : return wrapper->wrapDouble(objID, variable, getApparentDecel(typeID));
487 65 : case VAR_ACTIONSTEPLENGTH:
488 65 : return wrapper->wrapDouble(objID, variable, getActionStepLength(typeID));
489 77 : case VAR_IMPERFECTION:
490 77 : return wrapper->wrapDouble(objID, variable, getImperfection(typeID));
491 265 : case VAR_TAU:
492 265 : return wrapper->wrapDouble(objID, variable, getTau(typeID));
493 69 : case VAR_SPEED_FACTOR:
494 69 : return wrapper->wrapDouble(objID, variable, getSpeedFactor(typeID));
495 51 : case VAR_SPEED_DEVIATION:
496 51 : return wrapper->wrapDouble(objID, variable, getSpeedDeviation(typeID));
497 385 : case VAR_VEHICLECLASS:
498 770 : return wrapper->wrapString(objID, variable, getVehicleClass(typeID));
499 133 : case VAR_EMISSIONCLASS:
500 266 : return wrapper->wrapString(objID, variable, getEmissionClass(typeID));
501 56 : case VAR_SHAPECLASS:
502 112 : return wrapper->wrapString(objID, variable, getShapeClass(typeID));
503 74 : case VAR_WIDTH:
504 74 : return wrapper->wrapDouble(objID, variable, getWidth(typeID));
505 8 : case VAR_COLOR:
506 8 : return wrapper->wrapColor(objID, variable, getColor(typeID));
507 7 : case VAR_MINGAP_LAT:
508 7 : return wrapper->wrapDouble(objID, variable, getMinGapLat(typeID));
509 52 : case VAR_MAXSPEED_LAT:
510 52 : return wrapper->wrapDouble(objID, variable, getMaxSpeedLat(typeID));
511 52 : case VAR_LATALIGNMENT:
512 104 : return wrapper->wrapString(objID, variable, getLateralAlignment(typeID));
513 4 : case VAR_PERSON_CAPACITY:
514 4 : return wrapper->wrapInt(objID, variable, getPersonCapacity(typeID));
515 12 : case VAR_BOARDING_DURATION:
516 12 : return wrapper->wrapDouble(objID, variable, getBoardingDuration(typeID));
517 6 : case VAR_IMPATIENCE:
518 6 : return wrapper->wrapDouble(objID, variable, getImpatience(typeID));
519 3 : case VAR_SCALE:
520 3 : return wrapper->wrapDouble(objID, variable, getScale(typeID));
521 56 : case libsumo::VAR_PARAMETER:
522 56 : paramData->readUnsignedByte();
523 112 : return wrapper->wrapString(objID, variable, getParameter(objID, paramData->readString()));
524 19 : case libsumo::VAR_PARAMETER_WITH_KEY:
525 19 : paramData->readUnsignedByte();
526 38 : return wrapper->wrapStringPair(objID, variable, getParameterWithKey(objID, paramData->readString()));
527 : default:
528 : return false;
529 : }
530 : }
531 :
532 : }
533 :
534 :
535 : /****************************************************************************/
|