Eclipse SUMO - Simulation of Urban MObility
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-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 /****************************************************************************/
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 
27 #include <utils/common/StdDefs.h>
28 #include <utils/geom/GeomHelper.h>
29 #include <utils/xml/XMLSubSys.h>
31 #include "RealisticEngineModel.h"
32 
33 
34 // ===========================================================================
35 // method definitions
36 // ===========================================================================
38  className = "RealisticEngineModel";
39  dt_s = 0.01;
40  xmlFile = "vehicles.xml";
42 }
43 
44 
46 
47 
48 double 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 
56 }
57 
58 
59 double 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 
65 double RealisticEngineModel::speed_mpsToRpm(double speed_mps) {
66  return ep.__speedToRpmCoefficient * speed_mps * ep.gearRatios[currentGear];
67 }
68 
69 
70 double 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 
125 double 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 
130 double RealisticEngineModel::airDrag_N(double speed_mps) {
131  return ep.__airFrictionCoefficient * speed_mps * speed_mps;
132 }
133 
134 
135 double 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 
145 double RealisticEngineModel::gravityForce_N(double mass_kg, double slope = 0) {
146  return mass_kg * GRAVITY_MPS2 * sin(slope / 180 * M_PI);
147 }
148 
149 
151  return ep.__gravity;
152 }
153 
154 
155 double 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 
164 double RealisticEngineModel::opposingForce_N(double speed_mps) {
165  return airDrag_N(speed_mps) + rollingResistance_N(speed_mps) + gravityForce_N();
166 }
167 
168 
169 double RealisticEngineModel::maxNoSlipAcceleration_mps2(double slope, double frictionCoefficient) {
170  return frictionCoefficient * GRAVITY_MPS2 * cos(slope / 180 * M_PI);
171 }
172 
173 
176 }
177 
178 
180  return thrust_N / ep.__maxAccelerationCoefficient;
181 }
182 
183 
184 int 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 
202 }
203 
204 
206  if (rpm <= 0) {
207  return TAU_MAX;
208  } else {
209  if (ep.fixedTauBurn)
210  //in this case, tau_burn is fixed and is within __engineTauDe_s
211  {
212  return std::min(TAU_MAX, ep.__engineTau2 / rpm + ep.__engineTauDe_s);
213  } else
214  //in this case, tau_burn is dynamic and is within __engineTau1
215  {
216  return std::min(TAU_MAX, ep.__engineTau1 / rpm + ep.tauEx_s);
217  }
218  }
219 }
220 
221 
222 double RealisticEngineModel::getRealAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime timeStep) {
223  double realAccel_mps2;
224  //perform gear shifting, if needed
225  performGearShifting(speed_mps, accel_mps2);
226  //since we consider no clutch (clutch always engaged), 0 speed would mean 0 rpm, and thus
227  //0 available power. thus, the car could never start from a complete stop. so we assume
228  //a minimum speed of 1 m/s to compute engine power
229  double correctedSpeed = std::max(speed_mps, minSpeed_mps);
230  if (reqAccel_mps2 >= 0) {
231  //the system wants to accelerate
232  //compute what is the maximum acceleration that can be delivered by the engine
233  double engineAccel = maxEngineAcceleration_mps2(correctedSpeed);
234  //the maximum acceleration is given by the maximum acceleration the engine can provide minus friction forces
235  double maxAccel = engineAccel - thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
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  //use standard first order lag with time constant depending on engine rpm
240  realAccel_mps2 = alpha * reqAccel_mps2 + (1 - alpha) * accel_mps2;
241  //limit the actual acceleration by considering friction forces and the maximum acceleration considering tyres
242  realAccel_mps2 = std::min(std::min(realAccel_mps2, maxAccel), maxNoSlipAcceleration_mps2());
243  } else {
244  realAccel_mps2 = getRealBrakingAcceleration(speed_mps, accel_mps2, reqAccel_mps2, timeStep);
245  }
246  return realAccel_mps2;
247 }
248 
249 
250 void RealisticEngineModel::getEngineData(double speed_mps, int& gear, double& rpm) {
251  gear = currentGear;
252  rpm = speed_mpsToRpm(speed_mps);
253 }
254 
255 
256 double RealisticEngineModel::getRealBrakingAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime t) {
257  UNUSED_PARAMETER(t);
258  //compute which part of the deceleration is currently done by frictions
259  double frictionDeceleration = thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
260  //the maximum deceleration is what the vehicle can do given the tyres plus the friction forces (friction can make the vehicle brake stronger)
261  double maxDeceleration = -maxNoSlipAcceleration_mps2() - frictionDeceleration;
262  //compute the new brakes deceleration
263  double newBrakesAccel_mps2 = ep.__brakesAlpha * reqAccel_mps2 + ep.__brakesOneMinusAlpha * accel_mps2;
264  //keep actual deceleration within physical limits (considering that wind force can help us slowing down)
265  return std::max(maxDeceleration, newBrakesAccel_mps2);
266 
267 }
268 
269 
271  VehicleEngineHandler engineHandler(vehicleType);
272  if (!XMLSubSys::runParser(engineHandler, xmlFile)) {
273  throw ProcessError();
274  }
275  //copy loaded parameters into our engine parameters
276  ep = engineHandler.getEngineParameters();
277  ep.dt = dt_s;
279  //compute "minimum speed" to be used when computing maximum acceleration at speeds close to 0
281 }
282 
283 
284 void RealisticEngineModel::setParameter(const std::string parameter, const std::string& value) {
285  if (parameter == ENGINE_PAR_XMLFILE) {
286  xmlFile = value;
287  }
288  if (parameter == ENGINE_PAR_VEHICLE) {
289  vehicleType = value;
290  if (xmlFile != "") {
291  loadParameters();
292  }
293  }
294 }
295 
296 
297 void RealisticEngineModel::setParameter(const std::string parameter, double value) {
298  if (parameter == ENGINE_PAR_DT) {
299  dt_s = value;
300  }
301 }
302 
303 
304 void RealisticEngineModel::setParameter(const std::string parameter, int value) {
305  UNUSED_PARAMETER(parameter);
306  UNUSED_PARAMETER(value);
307 }
#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:35
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
double __airFrictionCoefficient
struct PolynomialEngineModelRpmToHp engineMapping
double __speedToRpmCoefficient
double __speedToThrustCoefficient
struct GearShiftingRules shiftingRule
double __maxNoSlipAcceleration
double __rpmToSpeedCoefficient
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.
Definition: XMLSubSys.cpp:148
#define M_PI
Definition: odrSpiral.cpp:45