Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
RealisticEngineModel.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-2023 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/****************************************************************************/
18// A detailed engine model
19/****************************************************************************/
20#include <config.h>
21
22#include <cmath>
23#include <stdio.h>
24#include <algorithm>
25#include <iostream>
26
29#include <utils/xml/XMLSubSys.h>
32
33
34// ===========================================================================
35// method definitions
36// ===========================================================================
43
44
46
47
48double RealisticEngineModel::rpmToSpeed_mps(double rpm, double wheelDiameter_m = 0.94,
49 double differentialRatio = 4.6, double gearRatio = 4.5) {
50 return rpm * wheelDiameter_m * M_PI / (differentialRatio * gearRatio * 60);
51}
52
53
57
58
59double RealisticEngineModel::speed_mpsToRpm(double speed_mps, double wheelDiameter_m,
60 double differentialRatio, double gearRatio) {
61 return speed_mps * differentialRatio * gearRatio * 60 / (wheelDiameter_m * M_PI);
62}
63
64
65double RealisticEngineModel::speed_mpsToRpm(double speed_mps) {
67}
68
69
70double RealisticEngineModel::speed_mpsToRpm(double speed_mps, double gearRatio) {
71 return ep.__speedToRpmCoefficient * speed_mps * gearRatio;
72}
73
74
76 double sum = engineMapping->x[0];
77 for (int i = 1; i < engineMapping->degree; i++) {
78 sum += engineMapping->x[i] + pow(rpm, i);
79 }
80 return sum;
81}
82
83
85 if (rpm >= ep.maxRpm) {
86 rpm = ep.maxRpm;
87 }
88 double sum = ep.engineMapping.x[0];
89 for (int i = 1; i < ep.engineMapping.degree; i++) {
90 sum += ep.engineMapping.x[i] * pow(rpm, i);
91 }
92 return sum;
93}
94
95
97 const struct EngineParameters::PolynomialEngineModelRpmToHp* engineMapping,
98 double wheelDiameter_m, double differentialRatio,
99 double gearRatio) {
100 double rpm = speed_mpsToRpm(speed_mps, wheelDiameter_m, differentialRatio, gearRatio);
101 return rpmToPower_hp(rpm, engineMapping);
102}
103
104
106 return rpmToPower_hp(speed_mpsToRpm(speed_mps));
107}
108
109
111 const struct EngineParameters::PolynomialEngineModelRpmToHp* engineMapping,
112 double wheelDiameter_m, double differentialRatio,
113 double gearRatio, double engineEfficiency) {
114 double power_hp = speed_mpsToPower_hp(speed_mps, engineMapping, wheelDiameter_m, differentialRatio, gearRatio);
115 return engineEfficiency * power_hp * HP_TO_W / speed_mps;
116}
117
118
120 double power_hp = speed_mpsToPower_hp(speed_mps);
121 return ep.__speedToThrustCoefficient * power_hp / speed_mps;
122}
123
124
125double RealisticEngineModel::airDrag_N(double speed_mps, double cAir, double a_m2, double rho_kgpm3) {
126 return 0.5 * cAir * a_m2 * rho_kgpm3 * speed_mps * speed_mps;
127}
128
129
130double RealisticEngineModel::airDrag_N(double speed_mps) {
131 return ep.__airFrictionCoefficient * speed_mps * speed_mps;
132}
133
134
135double RealisticEngineModel::rollingResistance_N(double speed_mps, double mass_kg, double cr1, double cr2) {
136 return mass_kg * GRAVITY_MPS2 * (cr1 + cr2 * speed_mps * speed_mps);
137}
138
139
141 return ep.__cr1 + ep.__cr2 * speed_mps * speed_mps;
142}
143
144
145double RealisticEngineModel::gravityForce_N(double mass_kg, double slope = 0) {
146 return mass_kg * GRAVITY_MPS2 * sin(slope / 180 * M_PI);
147}
148
149
153
154
155double RealisticEngineModel::opposingForce_N(double speed_mps, double mass_kg, double slope,
156 double cAir, double a_m2, double rho_kgpm3,
157 double cr1, double cr2) {
158 return airDrag_N(speed_mps, cAir, a_m2, rho_kgpm3) +
159 rollingResistance_N(speed_mps, mass_kg, cr1, cr2) +
160 gravityForce_N(mass_kg, slope);
161}
162
163
165 return airDrag_N(speed_mps) + rollingResistance_N(speed_mps) + gravityForce_N();
166}
167
168
169double RealisticEngineModel::maxNoSlipAcceleration_mps2(double slope, double frictionCoefficient) {
170 return frictionCoefficient * GRAVITY_MPS2 * cos(slope / 180 * M_PI);
171}
172
173
177
178
180 return thrust_N / ep.__maxAccelerationCoefficient;
181}
182
183
184int RealisticEngineModel::performGearShifting(double speed_mps, double acceleration_mps2) {
185 int newGear = 0;
186 const double delta = acceleration_mps2 >= 0 ? ep.shiftingRule.deltaRpm : -ep.shiftingRule.deltaRpm;
187 for (newGear = 0; newGear < ep.nGears - 1; newGear++) {
188 const double rpm = speed_mpsToRpm(speed_mps, ep.gearRatios[newGear]);
189 if (rpm >= ep.shiftingRule.rpm + delta) {
190 continue;
191 } else {
192 break;
193 }
194 }
195 currentGear = newGear;
196 return currentGear;
197}
198
199
201 const double maxEngineAcceleration = speed_mpsToThrust_N(speed_mps) / ep.__maxAccelerationCoefficient;
202 return std::min(maxEngineAcceleration, maxNoSlipAcceleration_mps2());
203}
204
205
207 if (rpm <= 0) {
208 return TAU_MAX;
209 } else {
210 if (ep.fixedTauBurn)
211 //in this case, tau_burn is fixed and is within __engineTauDe_s
212 {
213 return std::min(TAU_MAX, ep.__engineTau2 / rpm + ep.__engineTauDe_s);
214 } else
215 //in this case, tau_burn is dynamic and is within __engineTau1
216 {
217 return std::min(TAU_MAX, ep.__engineTau1 / rpm + ep.tauEx_s);
218 }
219 }
220}
221
222
223double RealisticEngineModel::getRealAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime timeStep) {
224 double realAccel_mps2;
225 //perform gear shifting, if needed
226 performGearShifting(speed_mps, accel_mps2);
227 //since we consider no clutch (clutch always engaged), 0 speed would mean 0 rpm, and thus
228 //0 available power. thus, the car could never start from a complete stop. so we assume
229 //a minimum speed of 1 m/s to compute engine power
230 double correctedSpeed = std::max(speed_mps, minSpeed_mps);
231 if (reqAccel_mps2 >= 0) {
232 //the system wants to accelerate
233 //the real engine acceleration is the minimum between what the engine can deliver, and what
234 //has been requested
235 double engineAccel = std::min(maxEngineAcceleration_mps2(correctedSpeed), reqAccel_mps2);
236 //now we need to computed delayed acceleration due to actuation lag
237 double tau = getEngineTimeConstant_s(speed_mpsToRpm(correctedSpeed));
238 double alpha = ep.dt / (tau + ep.dt);
239 //compute the acceleration provided by the engine, thus removing friction from current acceleration
240 double currentAccel_mps2 = accel_mps2 + thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
241 //use standard first order lag with time constant depending on engine rpm
242 //add back frictions resistance as well
243 realAccel_mps2 = alpha * engineAccel + (1 - alpha) * currentAccel_mps2 - thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
244 } else {
245 realAccel_mps2 = getRealBrakingAcceleration(speed_mps, accel_mps2, reqAccel_mps2, timeStep);
246 }
247 return realAccel_mps2;
248}
249
250
251void RealisticEngineModel::getEngineData(double speed_mps, int& gear, double& rpm) {
252 gear = currentGear;
253 rpm = speed_mpsToRpm(speed_mps);
254}
255
256
257double RealisticEngineModel::getRealBrakingAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime t) {
259 //compute which part of the deceleration is currently done by frictions
260 double frictionDeceleration = thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
261 //remove the part of the deceleration which is due to friction
262 double brakesAccel_mps2 = accel_mps2 + frictionDeceleration;
263 //compute the new brakes deceleration
264 double newBrakesAccel_mps2 = ep.__brakesAlpha * std::max(-ep.__maxNoSlipAcceleration, reqAccel_mps2) + ep.__brakesOneMinusAlpha * brakesAccel_mps2;
265 //our brakes limit is tires friction
266 newBrakesAccel_mps2 = std::max(-ep.__maxNoSlipAcceleration, newBrakesAccel_mps2);
267 //now we need to add back our friction deceleration
268 return newBrakesAccel_mps2 - frictionDeceleration;
269}
270
271
273 VehicleEngineHandler engineHandler(vehicleType);
274 if (!XMLSubSys::runParser(engineHandler, xmlFile)) {
275 throw ProcessError();
276 }
277 //copy loaded parameters into our engine parameters
278 ep = engineHandler.getEngineParameters();
279 ep.dt = dt_s;
281 //compute "minimum speed" to be used when computing maximum acceleration at speeds close to 0
283}
284
285
286void RealisticEngineModel::setParameter(const std::string parameter, const std::string& value) {
287 if (parameter == ENGINE_PAR_XMLFILE) {
288 xmlFile = value;
289 }
290 if (parameter == ENGINE_PAR_VEHICLE) {
291 vehicleType = value;
292 if (xmlFile != "") {
294 }
295 }
296}
297
298
299void RealisticEngineModel::setParameter(const std::string parameter, double value) {
300 if (parameter == ENGINE_PAR_DT) {
301 dt_s = value;
302 }
303}
304
305
306void RealisticEngineModel::setParameter(const std::string parameter, int value) {
307 UNUSED_PARAMETER(parameter);
308 UNUSED_PARAMETER(value);
309}
#define ENGINE_PAR_XMLFILE
Definition CC_Const.h:87
#define ENGINE_PAR_VEHICLE
Definition CC_Const.h:86
#define ENGINE_PAR_DT
Definition CC_Const.h:88
#define GRAVITY_MPS2
#define HP_TO_W
#define TAU_MAX
long long int SUMOTime
Definition GUI.h:36
#define UNUSED_PARAMETER(x)
Definition StdDefs.h:30
double __airFrictionCoefficient
struct PolynomialEngineModelRpmToHp engineMapping
double __speedToThrustCoefficient
struct GearShiftingRules shiftingRule
double __maxAccelerationCoefficient
double maxEngineAcceleration_mps2(double speed_mps)
void getEngineData(double speed_mps, int &gear, double &rpm)
double airDrag_N(double speed_mps, double cAir, double a_m2, double rho_kgpm3)
virtual double getRealAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime timeStep=0)
double speed_mpsToPower_hp(double speed_mps, const struct EngineParameters::PolynomialEngineModelRpmToHp *engineMapping, double wheelDiameter_m, double differentialRatio, double gearRatio)
double thrust_NToAcceleration_mps2(double thrust_N)
double opposingForce_N(double speed_mps, double mass_kg, double slope, double cAir, double a_m2, double rho_kgpm3, double cr1, double cr2)
double getRealBrakingAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime t)
double rpmToPower_hp(double rpm, const struct EngineParameters::PolynomialEngineModelRpmToHp *engineMapping)
double rpmToSpeed_mps(double rpm, double wheelDiameter_m, double differentialRatio, double gearRatio)
double speed_mpsToThrust_N(double speed_mps, const struct EngineParameters::PolynomialEngineModelRpmToHp *engineMapping, double wheelDiameter_m, double differentialRatio, double gearRatio, double engineEfficiency)
double speed_mpsToRpm(double speed_mps, double wheelDiameter_m, double differentialRatio, double gearRatio)
virtual void setParameter(const std::string parameter, const std::string &value)
double rollingResistance_N(double speed_mps, double mass_kg, double cr1, double cr2)
int performGearShifting(double speed_mps, double acceleration_mps2)
double getEngineTimeConstant_s(double rpm)
const EngineParameters & getEngineParameters()
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
#define M_PI
Definition odrSpiral.cpp:45