1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    MSVehicleType.cpp
11 /// @author  Christian Roessel
12 /// @author  Daniel Krajzewicz
13 /// @author  Jakob Erdmann
14 /// @author  Thimor Bohn
15 /// @author  Michael Behrisch
16 /// @date    Tue, 06 Mar 2001
17 /// @version $Id$
18 ///
19 // The car-following model and parameter
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 
28 #include <cassert>
29 #include <utils/iodevices/BinaryInputDevice.h>
30 #include <utils/options/OptionsCont.h>
31 #include <utils/common/FileHelpers.h>
32 #include <utils/common/RandHelper.h>
33 #include <utils/common/StringUtils.h>
34 #include <utils/vehicle/SUMOVTypeParameter.h>
35 #include <microsim/cfmodels/MSCFModel_Rail.h>
36 #include "MSNet.h"
37 #include "cfmodels/MSCFModel_IDM.h"
38 #include "cfmodels/MSCFModel_Kerner.h"
39 #include "cfmodels/MSCFModel_Krauss.h"
40 #include "cfmodels/MSCFModel_KraussOrig1.h"
41 #include "cfmodels/MSCFModel_KraussPS.h"
42 #include "cfmodels/MSCFModel_KraussX.h"
43 #include "cfmodels/MSCFModel_SmartSK.h"
44 #include "cfmodels/MSCFModel_Daniel1.h"
45 #include "cfmodels/MSCFModel_PWag2009.h"
46 #include "cfmodels/MSCFModel_Wiedemann.h"
47 #include "cfmodels/MSCFModel_ACC.h"
48 #include "cfmodels/MSCFModel_CACC.h"
49 #include "MSVehicleControl.h"
50 #include "cfmodels/MSCFModel_CC.h"
51 #include "MSVehicleType.h"
52 
53 
54 // ===========================================================================
55 // static members
56 // ===========================================================================
57 int MSVehicleType::myNextIndex = 0;
58 
59 
60 // ===========================================================================
61 // method definitions
62 // ===========================================================================
MSVehicleType(const SUMOVTypeParameter & parameter)63 MSVehicleType::MSVehicleType(const SUMOVTypeParameter& parameter)
64     : myParameter(parameter), myWarnedActionStepLengthTauOnce(false), myIndex(myNextIndex++), myCarFollowModel(nullptr), myOriginalType(nullptr) {
65     assert(getLength() > 0);
66     assert(getMaxSpeed() > 0);
67 
68     // Check if actionStepLength was set by user, if not init to global default
69     if (!myParameter.wasSet(VTYPEPARS_ACTIONSTEPLENGTH_SET)) {
70         myParameter.actionStepLength = MSGlobals::gActionStepLength;
71     }
72     myCachedActionStepLengthSecs = STEPS2TIME(myParameter.actionStepLength);
73 }
74 
75 
~MSVehicleType()76 MSVehicleType::~MSVehicleType() {
77     delete myCarFollowModel;
78 }
79 
80 
81 double
computeChosenSpeedDeviation(std::mt19937 * rng,const double minDev) const82 MSVehicleType::computeChosenSpeedDeviation(std::mt19937* rng, const double minDev) const {
83     return MAX2(minDev, myParameter.speedFactor.sample(rng));
84 }
85 
86 
87 // ------------ Setter methods
88 void
setLength(const double & length)89 MSVehicleType::setLength(const double& length) {
90     if (myOriginalType != nullptr && length < 0) {
91         myParameter.length = myOriginalType->getLength();
92     } else {
93         myParameter.length = length;
94     }
95     myParameter.parametersSet |= VTYPEPARS_LENGTH_SET;
96 }
97 
98 
99 void
setHeight(const double & height)100 MSVehicleType::setHeight(const double& height) {
101     if (myOriginalType != nullptr && height < 0) {
102         myParameter.height = myOriginalType->getHeight();
103     } else {
104         myParameter.height = height;
105     }
106     myParameter.parametersSet |= VTYPEPARS_HEIGHT_SET;
107 }
108 
109 
110 void
setMinGap(const double & minGap)111 MSVehicleType::setMinGap(const double& minGap) {
112     if (myOriginalType != nullptr && minGap < 0) {
113         myParameter.minGap = myOriginalType->getMinGap();
114     } else {
115         myParameter.minGap = minGap;
116     }
117     myParameter.parametersSet |= VTYPEPARS_MINGAP_SET;
118 }
119 
120 
121 void
setMinGapLat(const double & minGapLat)122 MSVehicleType::setMinGapLat(const double& minGapLat) {
123     if (myOriginalType != nullptr && minGapLat < 0) {
124         myParameter.minGapLat = myOriginalType->getMinGapLat();
125     } else {
126         myParameter.minGapLat = minGapLat;
127     }
128     myParameter.parametersSet |= VTYPEPARS_MINGAP_LAT_SET;
129 }
130 
131 
132 void
setMaxSpeed(const double & maxSpeed)133 MSVehicleType::setMaxSpeed(const double& maxSpeed) {
134     if (myOriginalType != nullptr && maxSpeed < 0) {
135         myParameter.maxSpeed = myOriginalType->getMaxSpeed();
136     } else {
137         myParameter.maxSpeed = maxSpeed;
138     }
139     myParameter.parametersSet |= VTYPEPARS_MAXSPEED_SET;
140 }
141 
142 
143 void
setMaxSpeedLat(const double & maxSpeedLat)144 MSVehicleType::setMaxSpeedLat(const double& maxSpeedLat) {
145     if (myOriginalType != nullptr && maxSpeedLat < 0) {
146         myParameter.maxSpeedLat = myOriginalType->getMaxSpeedLat();
147     } else {
148         myParameter.maxSpeedLat = maxSpeedLat;
149     }
150     myParameter.parametersSet |= VTYPEPARS_MAXSPEED_LAT_SET;
151 }
152 
153 
154 void
setVClass(SUMOVehicleClass vclass)155 MSVehicleType::setVClass(SUMOVehicleClass vclass) {
156     myParameter.vehicleClass = vclass;
157     myParameter.parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
158 }
159 
160 void
setPreferredLateralAlignment(LateralAlignment latAlignment)161 MSVehicleType::setPreferredLateralAlignment(LateralAlignment latAlignment) {
162     myParameter.latAlignment = latAlignment;
163     myParameter.parametersSet |= VTYPEPARS_LATALIGNMENT_SET;
164 }
165 
166 
167 void
setDefaultProbability(const double & prob)168 MSVehicleType::setDefaultProbability(const double& prob) {
169     if (myOriginalType != nullptr && prob < 0) {
170         myParameter.defaultProbability = myOriginalType->getDefaultProbability();
171     } else {
172         myParameter.defaultProbability = prob;
173     }
174     myParameter.parametersSet |= VTYPEPARS_PROBABILITY_SET;
175 }
176 
177 
178 void
setSpeedFactor(const double & factor)179 MSVehicleType::setSpeedFactor(const double& factor) {
180     if (myOriginalType != nullptr && factor < 0) {
181         myParameter.speedFactor.getParameter()[0] = myOriginalType->myParameter.speedFactor.getParameter()[0];
182     } else {
183         myParameter.speedFactor.getParameter()[0] = factor;
184     }
185     myParameter.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
186 }
187 
188 
189 void
setSpeedDeviation(const double & dev)190 MSVehicleType::setSpeedDeviation(const double& dev) {
191     if (myOriginalType != nullptr && dev < 0) {
192         myParameter.speedFactor.getParameter()[1] = myOriginalType->myParameter.speedFactor.getParameter()[1];
193     } else {
194         myParameter.speedFactor.getParameter()[1] = dev;
195     }
196     myParameter.parametersSet |= VTYPEPARS_SPEEDFACTOR_SET;
197 }
198 
199 
200 void
setActionStepLength(const SUMOTime actionStepLength,bool resetActionOffset)201 MSVehicleType::setActionStepLength(const SUMOTime actionStepLength, bool resetActionOffset) {
202     assert(actionStepLength >= 0.);
203     myParameter.parametersSet |= VTYPEPARS_ACTIONSTEPLENGTH_SET;
204 
205     if (myParameter.actionStepLength == actionStepLength) {
206         return;
207     }
208 
209     SUMOTime previousActionStepLength = myParameter.actionStepLength;
210     myParameter.actionStepLength = actionStepLength;
211     myCachedActionStepLengthSecs = STEPS2TIME(myParameter.actionStepLength);
212     check();
213 
214     if (isVehicleSpecific()) {
215         // don't perform vehicle lookup for singular vtype
216         return;
217     }
218 
219     // For non-singular vType reset all vehicle's actionOffsets
220     // Iterate through vehicles
221     MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
222     for (auto vehIt = vc.loadedVehBegin(); vehIt != vc.loadedVehEnd(); ++vehIt) {
223         MSVehicle* veh = static_cast<MSVehicle*>(vehIt->second);
224         if (&veh->getVehicleType() == this) {
225             // Found vehicle of this type. Perform requested actionOffsetReset
226             if (resetActionOffset) {
227                 veh->resetActionOffset();
228             } else {
229                 veh->updateActionOffset(previousActionStepLength, actionStepLength);
230             }
231         }
232     }
233 }
234 
235 
236 void
setEmissionClass(SUMOEmissionClass eclass)237 MSVehicleType::setEmissionClass(SUMOEmissionClass eclass) {
238     myParameter.emissionClass = eclass;
239     myParameter.parametersSet |= VTYPEPARS_EMISSIONCLASS_SET;
240 }
241 
242 
243 void
setColor(const RGBColor & color)244 MSVehicleType::setColor(const RGBColor& color) {
245     myParameter.color = color;
246     myParameter.parametersSet |= VTYPEPARS_COLOR_SET;
247 }
248 
249 
250 void
setWidth(const double & width)251 MSVehicleType::setWidth(const double& width) {
252     if (myOriginalType != nullptr && width < 0) {
253         myParameter.width = myOriginalType->getWidth();
254     } else {
255         myParameter.width = width;
256     }
257     myParameter.parametersSet |= VTYPEPARS_WIDTH_SET;
258 }
259 
260 void
setImpatience(const double impatience)261 MSVehicleType::setImpatience(const double impatience) {
262     if (myOriginalType != nullptr && impatience < 0) {
263         myParameter.impatience = myOriginalType->getImpatience();
264     } else {
265         myParameter.impatience = impatience;
266     }
267     myParameter.parametersSet |= VTYPEPARS_IMPATIENCE_SET;
268 }
269 
270 
271 void
setShape(SUMOVehicleShape shape)272 MSVehicleType::setShape(SUMOVehicleShape shape) {
273     myParameter.shape = shape;
274     myParameter.parametersSet |= VTYPEPARS_SHAPE_SET;
275 }
276 
277 
278 
279 // ------------ Static methods for building vehicle types
280 MSVehicleType*
build(SUMOVTypeParameter & from)281 MSVehicleType::build(SUMOVTypeParameter& from) {
282     MSVehicleType* vtype = new MSVehicleType(from);
283     const double decel = from.getCFParam(SUMO_ATTR_DECEL, SUMOVTypeParameter::getDefaultDecel(from.vehicleClass));
284     const double emergencyDecel = from.getCFParam(SUMO_ATTR_EMERGENCYDECEL, SUMOVTypeParameter::getDefaultEmergencyDecel(from.vehicleClass, decel, MSGlobals::gDefaultEmergencyDecel));
285     // by default decel and apparentDecel are identical
286     const double apparentDecel = from.getCFParam(SUMO_ATTR_APPARENTDECEL, decel);
287 
288     if (emergencyDecel < decel) {
289         WRITE_WARNING("Value of 'emergencyDecel' (" + toString(emergencyDecel) + ") should be higher than 'decel' (" + toString(decel) + ") for vType '" + from.id + "'.");
290     }
291     if (emergencyDecel < apparentDecel) {
292         WRITE_WARNING("Value of 'emergencyDecel' (" + toString(emergencyDecel) + ") is lower than 'apparentDecel' (" + toString(apparentDecel) + ") for vType '" + from.id + "' may cause collisions.");
293     }
294 
295     switch (from.cfModel) {
296         case SUMO_TAG_CF_IDM:
297             vtype->myCarFollowModel = new MSCFModel_IDM(vtype, false);
298             break;
299         case SUMO_TAG_CF_IDMM:
300             vtype->myCarFollowModel = new MSCFModel_IDM(vtype, true);
301             break;
302         case SUMO_TAG_CF_BKERNER:
303             vtype->myCarFollowModel = new MSCFModel_Kerner(vtype);
304             break;
305         case SUMO_TAG_CF_KRAUSS_ORIG1:
306             vtype->myCarFollowModel = new MSCFModel_KraussOrig1(vtype);
307             break;
308         case SUMO_TAG_CF_KRAUSS_PLUS_SLOPE:
309             vtype->myCarFollowModel = new MSCFModel_KraussPS(vtype);
310             break;
311         case SUMO_TAG_CF_KRAUSSX:
312             vtype->myCarFollowModel = new MSCFModel_KraussX(vtype);
313             break;
314         case SUMO_TAG_CF_SMART_SK:
315             vtype->myCarFollowModel = new MSCFModel_SmartSK(vtype);
316             break;
317         case SUMO_TAG_CF_DANIEL1:
318             vtype->myCarFollowModel = new MSCFModel_Daniel1(vtype);
319             break;
320         case SUMO_TAG_CF_PWAGNER2009:
321             vtype->myCarFollowModel = new MSCFModel_PWag2009(vtype);
322             break;
323         case SUMO_TAG_CF_WIEDEMANN:
324             vtype->myCarFollowModel = new MSCFModel_Wiedemann(vtype);
325             break;
326         case SUMO_TAG_CF_RAIL:
327             vtype->myCarFollowModel = new MSCFModel_Rail(vtype);
328             break;
329         case SUMO_TAG_CF_ACC:
330             vtype->myCarFollowModel = new MSCFModel_ACC(vtype);
331             break;
332         case SUMO_TAG_CF_CACC:
333             vtype->myCarFollowModel = new MSCFModel_CACC(vtype);
334             break;
335         case SUMO_TAG_CF_CC:
336             vtype->myCarFollowModel = new MSCFModel_CC(vtype);
337             break;
338         case SUMO_TAG_CF_KRAUSS:
339         default:
340             vtype->myCarFollowModel = new MSCFModel_Krauss(vtype);
341             break;
342     }
343     // init further param values
344     vtype->initParameters();
345     vtype->check();
346     return vtype;
347 }
348 
349 
350 MSVehicleType*
buildSingularType(const std::string & id) const351 MSVehicleType::buildSingularType(const std::string& id) const {
352     return duplicateType(id, false);
353 }
354 
355 
356 MSVehicleType*
duplicateType(const std::string & id,bool persistent) const357 MSVehicleType::duplicateType(const std::string& id, bool persistent) const {
358     MSVehicleType* vtype = new MSVehicleType(myParameter);
359     vtype->myParameter.id = id;
360     vtype->myCarFollowModel = myCarFollowModel->duplicate(vtype);
361     if (!persistent) {
362         vtype->myOriginalType = this;
363     }
364     if (!MSNet::getInstance()->getVehicleControl().addVType(vtype)) {
365         std::string singular = persistent ? "" : "singular ";
366         throw ProcessError("could not add " + singular + "type " + vtype->getID());
367     }
368     return vtype;
369 }
370 
371 void
check()372 MSVehicleType::check() {
373     if (!myWarnedActionStepLengthTauOnce
374             && myParameter.actionStepLength != DELTA_T
375             && STEPS2TIME(myParameter.actionStepLength) > getCarFollowModel().getHeadwayTime()) {
376         myWarnedActionStepLengthTauOnce = true;
377         std::stringstream s;
378         s << "Given action step length " << STEPS2TIME(myParameter.actionStepLength) << " for vehicle type '" << getID()
379           << "' is larger than its parameter tau (=" << getCarFollowModel().getHeadwayTime() << ")!"
380           << " This may lead to collisions. (This warning is only issued once per vehicle type).";
381         WRITE_WARNING(s.str());
382     }
383 }
384 
385 void
setAccel(double accel)386 MSVehicleType::setAccel(double accel) {
387     if (myOriginalType != nullptr && accel < 0) {
388         accel = myOriginalType->getCarFollowModel().getMaxAccel();
389     }
390     myCarFollowModel->setMaxAccel(accel);
391     myParameter.cfParameter[SUMO_ATTR_ACCEL] = toString(accel);
392 }
393 
394 void
setDecel(double decel)395 MSVehicleType::setDecel(double decel) {
396     if (myOriginalType != nullptr && decel < 0) {
397         decel = myOriginalType->getCarFollowModel().getMaxDecel();
398     }
399     myCarFollowModel->setMaxDecel(decel);
400     myParameter.cfParameter[SUMO_ATTR_DECEL] = toString(decel);
401 }
402 
403 void
setEmergencyDecel(double emergencyDecel)404 MSVehicleType::setEmergencyDecel(double emergencyDecel) {
405     if (myOriginalType != nullptr && emergencyDecel < 0) {
406         emergencyDecel = myOriginalType->getCarFollowModel().getEmergencyDecel();
407     }
408     myCarFollowModel->setEmergencyDecel(emergencyDecel);
409     myParameter.cfParameter[SUMO_ATTR_EMERGENCYDECEL] = toString(emergencyDecel);
410 }
411 
412 void
setApparentDecel(double apparentDecel)413 MSVehicleType::setApparentDecel(double apparentDecel) {
414     if (myOriginalType != nullptr && apparentDecel < 0) {
415         apparentDecel = myOriginalType->getCarFollowModel().getApparentDecel();
416     }
417     myCarFollowModel->setApparentDecel(apparentDecel);
418     myParameter.cfParameter[SUMO_ATTR_APPARENTDECEL] = toString(apparentDecel);
419 }
420 
421 void
setImperfection(double imperfection)422 MSVehicleType::setImperfection(double imperfection) {
423     if (myOriginalType != nullptr && imperfection < 0) {
424         imperfection = myOriginalType->getCarFollowModel().getImperfection();
425     }
426     myCarFollowModel->setImperfection(imperfection);
427     myParameter.cfParameter[SUMO_ATTR_SIGMA] = toString(imperfection);
428 }
429 
430 void
setTau(double tau)431 MSVehicleType::setTau(double tau) {
432     if (myOriginalType != nullptr && tau < 0) {
433         tau = myOriginalType->getCarFollowModel().getHeadwayTime();
434     }
435     myCarFollowModel->setHeadwayTime(tau);
436     myParameter.cfParameter[SUMO_ATTR_TAU] = toString(tau);
437 }
438 
439 
440 void
initParameters()441 MSVehicleType::initParameters() {
442     if (myParameter.knowsParameter("carriageLength")) {
443         myParameter.carriageLength = StringUtils::toDouble(myParameter.getParameter("carriageLength"));
444     } else if (myParameter.wasSet(VTYPEPARS_SHAPE_SET)) {
445         switch (myParameter.shape) {
446             case SVS_BUS_FLEXIBLE:
447                 myParameter.carriageLength = 8.25; // 16.5 overall, 2 modules http://de.wikipedia.org/wiki/Ikarus_180
448                 myParameter.carriageGap = 0;
449                 break;
450             case SVS_RAIL:
451                 myParameter.carriageLength = 24.5; // http://de.wikipedia.org/wiki/UIC-Y-Wagen_%28DR%29
452                 break;
453             case SVS_RAIL_CAR:
454                 myParameter.carriageLength = 16.85;  // 67.4m overall, 4 carriages http://de.wikipedia.org/wiki/DB-Baureihe_423
455                 break;
456             case SVS_RAIL_CARGO:
457                 myParameter.carriageLength = 13.86; // UIC 571-1 http://de.wikipedia.org/wiki/Flachwagen
458                 break;
459             case SVS_TRUCK_SEMITRAILER:
460                 myParameter.carriageLength = 13.5;
461                 myParameter.locomotiveLength = 2.5;
462                 myParameter.carriageGap = 0.5;
463                 break;
464             case SVS_TRUCK_1TRAILER:
465                 myParameter.carriageLength = 6.75;
466                 myParameter.locomotiveLength = 2.5 + 6.75;
467                 myParameter.carriageGap = 0.5;
468                 break;
469             default:
470                 break;
471         }
472     }
473     if (myParameter.knowsParameter("locomotiveLength")) {
474         myParameter.locomotiveLength = StringUtils::toDouble(myParameter.getParameter("locomotiveLength"));
475     } else if (myParameter.locomotiveLength <= 0) {
476         myParameter.locomotiveLength = myParameter.carriageLength;
477     }
478     if (myParameter.knowsParameter("carriageGap")) {
479         myParameter.carriageGap = StringUtils::toDouble(myParameter.getParameter("carriageGap"));
480     }
481 }
482 
483 /****************************************************************************/
484 
485