TORCS  1.3.10
The Open Racing Car Simulator
Loading...
Searching...
No Matches
engine.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 file : engine.cpp
4 created : Sun Mar 19 00:06:55 CET 2000
5 copyright : (C) 2000-2026 by Eric Espie, Bernhard Wymann
6 email : berniw@bluewin.ch
7
8***************************************************************************/
9
10/***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19#include "sim.h"
20#include <portability.h>
21
22void
24{
25 void *hdle = car->params;
26 int i;
27 tdble maxTq;
28 tdble rpmMaxTq = 0;
29 const int IDXSIZE = 64;
30 char idx[IDXSIZE];
31 tEngineCurveElem *data;
32 struct tEdesc {
33 tdble rpm;
34 tdble tq;
35 } *edesc;
36
37
38 car->engine.revsLimiter = GfParmGetNum(hdle, SECT_ENGINE, PRM_REVSLIM, (char*)NULL, 800);
39 car->carElt->_enginerpmRedLine = car->engine.revsLimiter;
40 car->engine.revsMax = GfParmGetNum(hdle, SECT_ENGINE, PRM_REVSMAX, (char*)NULL, 1000);
41 car->carElt->_enginerpmMax = car->engine.revsMax;
42 car->engine.tickover = GfParmGetNum(hdle, SECT_ENGINE, PRM_TICKOVER, (char*)NULL, 150);
43 car->engine.I = GfParmGetNum(hdle, SECT_ENGINE, PRM_INERTIA, (char*)NULL, 0.2423f);
44 car->engine.fuelcons = GfParmGetNum(hdle, SECT_ENGINE, PRM_FUELCONS, (char*)NULL, 0.0622f);
45 car->engine.brakeCoeff = GfParmGetNum(hdle, SECT_ENGINE, PRM_ENGBRKCOEFF, (char*)NULL, 0.33f);
46 car->engine.exhaust_pressure = 0.0f;
47 car->engine.exhaust_refract = 0.1f;
49
50 snprintf(idx, IDXSIZE, "%s/%s", SECT_ENGINE, ARR_DATAPTS);
51 car->engine.curve.nbPts = GfParmGetEltNb(hdle, idx);
52 edesc = (struct tEdesc*)malloc((car->engine.curve.nbPts + 1) * sizeof(struct tEdesc));
53
54 for (i = 0; i < car->engine.curve.nbPts; i++) {
55 snprintf(idx, IDXSIZE, "%s/%s/%d", SECT_ENGINE, ARR_DATAPTS, i+1);
56 edesc[i].rpm = GfParmGetNum(hdle, idx, PRM_RPM, (char*)NULL, car->engine.revsMax);
57 edesc[i].tq = GfParmGetNum(hdle, idx, PRM_TQ, (char*)NULL, 0);
58 }
59 edesc[i].rpm = edesc[i - 1].rpm;
60 edesc[i].tq = edesc[i - 1].tq;
61
62 maxTq = 0;
63 car->engine.curve.maxPw = 0;
64 car->engine.curve.data = (tEngineCurveElem *)malloc(car->engine.curve.nbPts * sizeof(tEngineCurveElem));
65 for(i = 0; i < car->engine.curve.nbPts; i++) {
66 data = &(car->engine.curve.data[i]);
67
68 data->rads = edesc[i+1].rpm;
69 if ((data->rads >= car->engine.tickover)
70 && (edesc[i+1].tq > maxTq)
71 && (data->rads < car->engine.revsLimiter)) {
72 maxTq = edesc[i+1].tq;
73 rpmMaxTq = data->rads;
74 }
75 if ((data->rads >= car->engine.tickover)
76 && (data->rads * edesc[i+1].tq > car->engine.curve.maxPw)
77 && (data->rads < car->engine.revsLimiter)) {
78 car->engine.curve.TqAtMaxPw = edesc[i+1].tq;
79 car->engine.curve.maxPw = data->rads * edesc[i+1].tq;
80 car->engine.curve.rpmMaxPw = data->rads;
81 }
82
83 /* Precompute the straight-line equation for the torque curve between the current map point and the next one.
84 * For the segment [rpm_i, rpm_(i+1)], torque is interpolated as:
85 *
86 * T(rpm) = a * rpm + b
87 *
88 * where:
89 * a = slope of the segment
90 * b = intercept chosen so that the line passes through point i
91 *
92 * This lets SimEngineUpdateTq() evaluate the maximum engine torque quickly
93 * at runtime without recomputing the interpolation formula in every timestep.
94 */
95 data->a = (edesc[i+1].tq - edesc[i].tq) / (edesc[i+1].rpm - edesc[i].rpm);
96 data->b = edesc[i].tq - data->a * edesc[i].rpm;
97 }
98
99 car->engine.curve.maxTq = maxTq;
100 car->carElt->_engineMaxTq = maxTq;
101 car->carElt->_enginerpmMaxTq = rpmMaxTq;
102 car->carElt->_engineMaxPw = car->engine.curve.maxPw;
103 car->carElt->_enginerpmMaxPw = car->engine.curve.rpmMaxPw;
104
105 car->engine.rads = car->engine.tickover;
106
107 free(edesc);
108}
109
110/* Update torque output with engine rpm and accelerator command */
111void
113{
114 int i;
115 tEngine *engine = &(car->engine);
116 tEngineCurve *curve = &(engine->curve);
117
118 if ((car->fuel <= 0.0f) || (car->carElt->_state & (RM_CAR_STATE_BROKEN | RM_CAR_STATE_ELIMINATED))) {
119 engine->rads = 0;
120 engine->Tq = 0;
121 return;
122 }
123
124 if (engine->rads > engine->revsLimiter) {
125 engine->rads = engine->revsLimiter;
126 engine->Tq = 0;
127 } else {
128 for (i = 0; i < car->engine.curve.nbPts; i++) {
129 if (engine->rads < curve->data[i].rads) {
130 tdble Tmax = engine->rads * curve->data[i].a + curve->data[i].b;
131 tdble EngBrkK = engine->brakeCoeff * (engine->rads - engine->tickover) / (engine->revsMax - engine->tickover);
132
133 engine->Tq = Tmax * (car->ctrl->accelCmd * (1.0f + EngBrkK) - EngBrkK);
134 // Engines comsume always fuel (needed for keeping the process running, inner friction,
135 // braking, accelerating pistons, etc.
136 // TODO: Evaluate if it is worth implementing it.
137 car->fuel -= (tdble) fabs(engine->Tq) * engine->rads * engine->fuelcons * 0.0000001f * SimDeltaTime;
138 if (car->fuel <= 0.0) {
139 car->fuel = 0.0;
140 }
141 return;
142 }
143 }
144 }
145}
146
147/*
148 * Function
149 * SimEngineUpdateRpm
150 *
151 * Description
152 * update engine RPM with wheels RPM
153 *
154 * Parameters
155 * car and axle RPM
156 *
157 * Return
158 * axle rpm for wheel update
159 * 0 if no wheel update
160 */
161tdble
163{
164 tTransmission *trans = &(car->transmission);
165 tClutch *clutch = &(trans->clutch);
166 tEngine *engine = &(car->engine);
167 float freerads;
168 float transfer;
169
170
171 if (car->fuel <= 0.0) {
172 engine->rads = 0;
173 clutch->state = CLUTCH_APPLIED;
174 clutch->transferValue = 0.0;
175 return 0.0;
176 }
177
178 freerads = engine->rads;
179 freerads += engine->Tq / engine->I * SimDeltaTime;
180 {
181 tdble dp = engine->pressure;
182 engine->pressure = engine->pressure*0.9f + 0.1f*engine->Tq;
183 dp = (0.001f* (tdble) fabs(engine->pressure - dp));
184 dp = (tdble) fabs(dp);
185 tdble rth = urandom();
186 if (dp > rth) {
187 engine->exhaust_pressure += rth;
188 }
189 engine->exhaust_pressure *= 0.9f;
190 car->carElt->priv.smoke += 5.0f*engine->exhaust_pressure;
191 car->carElt->priv.smoke *= 0.99f;
192 }
193
194 if ((clutch->transferValue > 0.01f) && (trans->gearbox.gear)) {
195 transfer = clutch->transferValue * clutch->transferValue * clutch->transferValue * clutch->transferValue;
196
197 engine->rads = axleRpm * trans->curOverallRatio * transfer + freerads * (1.0f - transfer);
198
199 if (engine->rads < engine->tickover) {
200 engine->rads = engine->tickover;
201 } else if (engine->rads > engine->revsMax) {
202 engine->rads = engine->revsMax;
203 return engine->revsMax / trans->curOverallRatio;
204 }
205 } else {
206 engine->rads = freerads;
207 }
208 return 0.0;
209}
210
211void
213{
214 free(car->engine.curve.data);
215}
real urandom()
#define PRM_REVSMAX
Definition car.h:591
#define PRM_FUELCONS
Definition car.h:596
#define ARR_DATAPTS
Definition car.h:595
#define PRM_ENGBRKCOEFF
Definition car.h:597
#define PRM_REVSLIM
Definition car.h:590
#define SECT_ENGINE
Definition car.h:504
#define RM_CAR_STATE_BROKEN
Engine no more working.
Definition car.h:218
#define PRM_TQ
Definition car.h:594
#define PRM_TICKOVER
Definition car.h:592
#define PRM_INERTIA
Definition car.h:529
#define PRM_RPM
Definition car.h:593
#define RM_CAR_STATE_ELIMINATED
Eliminated due to rules infringement.
Definition car.h:220
void SimEngineConfig(tCar *car)
Definition engine.cpp:23
void SimEngineShutdown(tCar *car)
Definition engine.cpp:212
void SimEngineUpdateTq(tCar *car)
Definition engine.cpp:112
tdble SimEngineUpdateRpm(tCar *car, tdble axleRpm)
Definition engine.cpp:162
float tdble
Floating point type used in TORCS.
Definition tgf.h:47
tdble GfParmGetNum(void *handle, const char *path, const char *key, const char *unit, tdble deflt)
Get a numerical parameter from the parameter set handle.
Definition params.cpp:2534
int GfParmGetEltNb(void *handle, const char *path)
Count the number of subsections in a section in the parameter set handle.
Definition params.cpp:2243
tdble rulesFuelFactor
Definition simu.cpp:39
tdble SimDeltaTime
Definition simu.cpp:35
tPrivCar priv
private
Definition car.h:463
tdble accelCmd
Accelerator command [0.0, 1.0].
Definition car.h:348
tdble fuel
Definition carstruct.h:63
void * params
Definition carstruct.h:39
tTransmission transmission
Definition carstruct.h:51
tCarElt * carElt
Definition carstruct.h:40
tEngine engine
Definition carstruct.h:52
tCarCtrl * ctrl
Definition carstruct.h:38
tdble transferValue
int nbPts
Definition engine.h:35
tEngineCurveElem * data
Definition engine.h:36
tdble maxTq
Definition engine.h:30
tdble rpmMaxPw
Definition engine.h:32
tdble TqAtMaxPw
Definition engine.h:33
tdble maxPw
Definition engine.h:31
tdble revsMax
Definition engine.h:43
tdble pressure
Definition engine.h:50
tdble Tq
Definition engine.h:47
tdble revsLimiter
Definition engine.h:42
tdble I
Definition engine.h:45
tdble exhaust_refract
Definition engine.h:52
tdble rads
Definition engine.h:46
tdble fuelcons
Definition engine.h:48
tdble tickover
Definition engine.h:44
tdble brakeCoeff
Definition engine.h:49
tdble exhaust_pressure
Definition engine.h:51
tEngineCurve curve
Definition engine.h:41
float smoke
Definition car.h:310
tdble curOverallRatio
tGearbox gearbox
#define CLUTCH_APPLIED