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