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.org/sumo
3 // Copyright (C) 2001-2020 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 
21 #include "RealisticEngineModel.h"
22 #include <cmath>
23 //define M_PI if this is not defined in <cmath>
24 #ifndef M_PI
25 #define M_PI 3.14159265358979323846
26 #endif
27 #include <stdio.h>
28 #include <iostream>
29 
30 #include <xercesc/sax2/SAX2XMLReader.hpp>
31 #include <xercesc/sax/EntityResolver.hpp>
32 #include <xercesc/sax/InputSource.hpp>
33 #include <xercesc/sax2/XMLReaderFactory.hpp>
34 
36 #include "utils/common/StdDefs.h"
37 #include <algorithm>
38 
40  className = "RealisticEngineModel";
41  dt_s = 0.01;
42  xmlFile = "vehicles.xml";
44 }
45 
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 
55 }
56 
57 double RealisticEngineModel::speed_mpsToRpm(double speed_mps, double wheelDiameter_m,
58  double differentialRatio, double gearRatio) {
59  return speed_mps * differentialRatio * gearRatio * 60 / (wheelDiameter_m * M_PI);
60 }
61 
62 double RealisticEngineModel::speed_mpsToRpm(double speed_mps) {
63  return ep.__speedToRpmCoefficient * speed_mps * ep.gearRatios[currentGear];
64 }
65 
66 double RealisticEngineModel::speed_mpsToRpm(double speed_mps, double gearRatio) {
67  return ep.__speedToRpmCoefficient * speed_mps * gearRatio;
68 }
69 
71  double sum = engineMapping->x[0];
72  for (int i = 1; i < engineMapping->degree; i++) {
73  sum += engineMapping->x[i] + pow(rpm, i);
74  }
75  return sum;
76 }
77 
79  if (rpm >= ep.maxRpm) {
80  rpm = ep.maxRpm;
81  }
82  double sum = ep.engineMapping.x[0];
83  for (int i = 1; i < ep.engineMapping.degree; i++) {
84  sum += ep.engineMapping.x[i] * pow(rpm, i);
85  }
86  return sum;
87 }
88 
90  const struct EngineParameters::PolynomialEngineModelRpmToHp* engineMapping,
91  double wheelDiameter_m, double differentialRatio,
92  double gearRatio) {
93  double rpm = speed_mpsToRpm(speed_mps, wheelDiameter_m, differentialRatio, gearRatio);
94  return rpmToPower_hp(rpm, engineMapping);
95 }
96 
98  return rpmToPower_hp(speed_mpsToRpm(speed_mps));
99 }
100 
102  const struct EngineParameters::PolynomialEngineModelRpmToHp* engineMapping,
103  double wheelDiameter_m, double differentialRatio,
104  double gearRatio, double engineEfficiency) {
105  double power_hp = speed_mpsToPower_hp(speed_mps, engineMapping, wheelDiameter_m, differentialRatio, gearRatio);
106  return engineEfficiency * power_hp * HP_TO_W / speed_mps;
107 }
108 
110  double power_hp = speed_mpsToPower_hp(speed_mps);
111  return ep.__speedToThrustCoefficient * power_hp / speed_mps;
112 }
113 
114 double RealisticEngineModel::airDrag_N(double speed_mps, double cAir, double a_m2, double rho_kgpm3) {
115  return 0.5 * cAir * a_m2 * rho_kgpm3 * speed_mps * speed_mps;
116 }
117 double RealisticEngineModel::airDrag_N(double speed_mps) {
118  return ep.__airFrictionCoefficient * speed_mps * speed_mps;
119 }
120 
121 double RealisticEngineModel::rollingResistance_N(double speed_mps, double mass_kg, double cr1, double cr2) {
122  return mass_kg * GRAVITY_MPS2 * (cr1 + cr2 * speed_mps * speed_mps);
123 }
125  return ep.__cr1 + ep.__cr2 * speed_mps * speed_mps;
126 }
127 
128 double RealisticEngineModel::gravityForce_N(double mass_kg, double slope = 0) {
129  return mass_kg * GRAVITY_MPS2 * sin(slope / 180 * M_PI);
130 }
131 
133  return ep.__gravity;
134 }
135 
136 double RealisticEngineModel::opposingForce_N(double speed_mps, double mass_kg, double slope,
137  double cAir, double a_m2, double rho_kgpm3,
138  double cr1, double cr2) {
139  return airDrag_N(speed_mps, cAir, a_m2, rho_kgpm3) +
140  rollingResistance_N(speed_mps, mass_kg, cr1, cr2) +
141  gravityForce_N(mass_kg, slope);
142 }
143 double RealisticEngineModel::opposingForce_N(double speed_mps) {
144  return airDrag_N(speed_mps) + rollingResistance_N(speed_mps) + gravityForce_N();
145 }
146 
147 double RealisticEngineModel::maxNoSlipAcceleration_mps2(double slope, double frictionCoefficient) {
148  return frictionCoefficient * GRAVITY_MPS2 * cos(slope / 180 * M_PI);
149 }
150 
153 }
154 
156  return thrust_N / ep.__maxAccelerationCoefficient;
157 }
158 
159 int RealisticEngineModel::performGearShifting(double speed_mps, double acceleration_mps2) {
160  int newGear = 0;
161  const double delta = acceleration_mps2 >= 0 ? ep.shiftingRule.deltaRpm : -ep.shiftingRule.deltaRpm;
162  for (newGear = 0; newGear < ep.nGears - 1; newGear++) {
163  const double rpm = speed_mpsToRpm(speed_mps, ep.gearRatios[newGear]);
164  if (rpm >= ep.shiftingRule.rpm + delta) {
165  continue;
166  } else {
167  break;
168  }
169  }
170  currentGear = newGear;
171  return currentGear;
172 }
173 
175  const double maxEngineAcceleration = speed_mpsToThrust_N(speed_mps) / ep.__maxAccelerationCoefficient;
176  return std::min(maxEngineAcceleration, maxNoSlipAcceleration_mps2());
177 }
178 
180  if (rpm <= 0) {
181  return TAU_MAX;
182  } else {
183  if (ep.fixedTauBurn)
184  //in this case, tau_burn is fixed and is within __engineTauDe_s
185  {
186  return std::min(TAU_MAX, ep.__engineTau2 / rpm + ep.__engineTauDe_s);
187  } else
188  //in this case, tau_burn is dynamic and is within __engineTau1
189  {
190  return std::min(TAU_MAX, ep.__engineTau1 / rpm + ep.tauEx_s);
191  }
192  }
193 }
194 
195 double RealisticEngineModel::getRealAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime timeStep) {
196 
197  double realAccel_mps2;
198  //perform gear shifting, if needed
199  performGearShifting(speed_mps, accel_mps2);
200  //since we consider no clutch (clutch always engaged), 0 speed would mean 0 rpm, and thus
201  //0 available power. thus, the car could never start from a complete stop. so we assume
202  //a minimum speed of 1 m/s to compute engine power
203  double correctedSpeed = std::max(speed_mps, minSpeed_mps);
204  if (reqAccel_mps2 >= 0) {
205  //the system wants to accelerate
206  //the real engine acceleration is the minimum between what the engine can deliver, and what
207  //has been requested
208  double engineAccel = std::min(maxEngineAcceleration_mps2(correctedSpeed), reqAccel_mps2);
209  //now we need to computed delayed acceleration due to actuation lag
210  double tau = getEngineTimeConstant_s(speed_mpsToRpm(correctedSpeed));
211  double alpha = ep.dt / (tau + ep.dt);
212  //compute the acceleration provided by the engine, thus removing friction from current acceleration
213  double currentAccel_mps2 = accel_mps2 + thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
214  //use standard first order lag with time constant depending on engine rpm
215  //add back frictions resistance as well
216  realAccel_mps2 = alpha * engineAccel + (1 - alpha) * currentAccel_mps2 - thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
217  } else {
218  realAccel_mps2 = getRealBrakingAcceleration(speed_mps, accel_mps2, reqAccel_mps2, timeStep);
219  }
220 
221  return realAccel_mps2;
222 }
223 
224 void RealisticEngineModel::getEngineData(double speed_mps, int& gear, double& rpm) {
225  gear = currentGear;
226  rpm = speed_mpsToRpm(speed_mps);
227 }
228 
229 double RealisticEngineModel::getRealBrakingAcceleration(double speed_mps, double accel_mps2, double reqAccel_mps2, SUMOTime t) {
230 
231  UNUSED_PARAMETER(t);
232  //compute which part of the deceleration is currently done by frictions
233  double frictionDeceleration = thrust_NToAcceleration_mps2(opposingForce_N(speed_mps));
234  //remove the part of the deceleration which is due to friction
235  double brakesAccel_mps2 = accel_mps2 + frictionDeceleration;
236  //compute the new brakes deceleration
237  double newBrakesAccel_mps2 = ep.__brakesAlpha * std::max(-ep.__maxNoSlipAcceleration, reqAccel_mps2) + ep.__brakesOneMinusAlpha * brakesAccel_mps2;
238  //our brakes limit is tires friction
239  newBrakesAccel_mps2 = std::max(-ep.__maxNoSlipAcceleration, newBrakesAccel_mps2);
240  //now we need to add back our friction deceleration
241  return newBrakesAccel_mps2 - frictionDeceleration;
242 
243 }
244 
246 
247  std::string xmlFile, vehicleType;
248 
251 
252  loadParameters();
253 
254 }
255 
257  //initialize xerces library
258  XERCES_CPP_NAMESPACE::XMLPlatformUtils::Initialize();
259  //create our xml reader
260  XERCES_CPP_NAMESPACE::SAX2XMLReader* reader = XERCES_CPP_NAMESPACE::XMLReaderFactory::createXMLReader();
261  if (reader == 0) {
262  std::cout << "The XML-parser could not be build." << std::endl;
263  }
264  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgXercesSchema, true);
265  reader->setFeature(XERCES_CPP_NAMESPACE::XMLUni::fgSAX2CoreValidation, true);
266 
267  //VehicleEngineHandler is our SAX parser
269  reader->setContentHandler(engineHandler);
270  reader->setErrorHandler(engineHandler);
271  try {
272  //parse the document. if any error is present in the xml file, the simulation will be closed
273  reader->parse(xmlFile.c_str());
274  //copy loaded parameters into our engine parameters
275  ep = engineHandler->getEngineParameters();
276  ep.dt = dt_s;
278  //compute "minimum speed" to be used when computing maximum acceleration at speeds close to 0
280  } catch (XERCES_CPP_NAMESPACE::SAXException&) {
281  std::cerr << "Error while parsing " << xmlFile << ": Does the file exist?" << std::endl;
282  exit(1);
283  }
284 
285  //delete handler and reader
286  delete engineHandler;
287  delete reader;
288 }
289 
290 void RealisticEngineModel::setParameter(const std::string parameter, const std::string& value) {
291  if (parameter == ENGINE_PAR_XMLFILE) {
292  xmlFile = value;
293  }
294  if (parameter == ENGINE_PAR_VEHICLE) {
295  vehicleType = value;
296  if (xmlFile != "") {
297  loadParameters();
298  }
299  }
300 }
301 void RealisticEngineModel::setParameter(const std::string parameter, double value) {
302  if (parameter == ENGINE_PAR_DT) {
303  dt_s = value;
304  }
305 }
306 void 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:86
#define ENGINE_PAR_VEHICLE
Definition: CC_Const.h:85
#define ENGINE_PAR_DT
Definition: CC_Const.h:87
#define GRAVITY_MPS2
#define HP_TO_W
#define TAU_MAX
#define M_PI
long long int SUMOTime
Definition: SUMOTime.h:31
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:29
double __airFrictionCoefficient
struct PolynomialEngineModelRpmToHp engineMapping
double __speedToRpmCoefficient
double __speedToThrustCoefficient
struct GearShiftingRules shiftingRule
double __maxNoSlipAcceleration
double __rpmToSpeedCoefficient
double __maxAccelerationCoefficient
std::map< std::string, std::string > ParMap
void parseParameter(const ParMap &parameters, std::string parameter, double &value)
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()