1 /***************************************************************************
2
3 file : susp.cpp
4 created : Sun Mar 19 00:08:41 CET 2000
5 copyright : (C) 2000-2016 by Eric Espie, Bernhard Wymann
6 email : torcs@free.fr
7 version : $Id: susp.cpp,v 1.10.2.10 2016/03/19 14:47:05 berniw Exp $
8
9 ***************************************************************************/
10
11 /***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20 #include <stdio.h>
21 #include "sim.h"
22
23 /*
24 * b2 and b3 calculus
25 */
initDamper(tSuspension * susp)26 static void initDamper(tSuspension *susp)
27 {
28 tDamper *damp;
29
30 damp = &(susp->damper);
31 damp->bump.b2 = (damp->bump.C1 - damp->bump.C2) * damp->bump.v1;
32 damp->rebound.b2 = (damp->rebound.C1 - damp->rebound.C2) * damp->rebound.v1;
33 }
34
35
36
37
38 /*
39 * get damper force
40 */
damperForce(tSuspension * susp)41 static tdble damperForce(tSuspension *susp)
42 {
43 tDamperDef *dampdef;
44 tdble f;
45 tdble av;
46 tdble v;
47
48 v = susp->v;
49
50 if (fabs(v) > 10.0f) {
51 v = SIGN(v) * 10.0f;
52 }
53
54 if (v < 0.0f) {
55 /* rebound */
56 dampdef = &(susp->damper.rebound);
57 } else {
58 /* bump */
59 dampdef = &(susp->damper.bump);
60 }
61
62 av = fabs(v);
63 if (av < dampdef->v1) {
64 f = (dampdef->C1 * av);
65 } else {
66 f = (dampdef->C2 * av + dampdef->b2);
67 }
68
69 f *= SIGN(v);
70
71 return f;
72 }
73
74
75
76
77 /*
78 * get spring force
79 */
springForce(tSuspension * susp)80 static tdble springForce(tSuspension *susp)
81 {
82 tSpring *spring = &(susp->spring);
83 tdble f;
84
85 /* K is < 0 */
86 f = spring->K * (susp->x - spring->x0) + spring->F0;
87 if (f < 0.0f) {
88 // Compression spring, so the force can never change the sign.
89 f = 0.0f;
90 }
91
92 return f;
93 }
94
95
96
97
SimSuspCheckIn(tSuspension * susp)98 void SimSuspCheckIn(tSuspension *susp)
99 {
100 susp->state = 0;
101 if (susp->x < susp->spring.packers) {
102 // Packers are not scaled with susp->spring.bellcrank, because they are a hard
103 // rubber element or plate spring packs directly mounted on the piston of the
104 // damper.
105 susp->x = susp->spring.packers;
106 susp->state = SIM_SUSP_COMP;
107 }
108
109 susp->x *= susp->spring.bellcrank;
110 if (susp->x > susp->spring.xMax) {
111 susp->x = susp->spring.xMax;
112 susp->state = SIM_SUSP_EXT;
113 }
114 }
115
116
117
118
SimSuspUpdate(tSuspension * susp)119 void SimSuspUpdate(tSuspension *susp)
120 {
121 tdble internalForce = springForce(susp) + damperForce(susp);
122 if (internalForce <= 0.0f) {
123 // The damping can at its best cancel out the spring force. Requred because
124 // of numerical integration artefacts with (if the velocity is 0 there is no
125 // damping, so the spring accelarates the system for one time step; if the
126 // damping is set very high this can result in a counterforce larger than the
127 // spring force in the next timestep)
128 susp->force = 0.0f;
129 } else {
130 susp->force = internalForce * susp->spring.bellcrank;
131 }
132 }
133
134
135
136
SimSuspConfig(void * hdle,const char * section,tSuspension * susp,tdble F0,tdble X0)137 void SimSuspConfig(void *hdle, const char *section, tSuspension *susp, tdble F0, tdble X0)
138 {
139 susp->spring.K = GfParmGetNum(hdle, section, PRM_SPR, (char*)NULL, 175000.0f);
140 susp->spring.xMax = GfParmGetNum(hdle, section, PRM_SUSPCOURSE, (char*)NULL, 0.5f);
141 susp->spring.bellcrank = GfParmGetNum(hdle, section, PRM_BELLCRANK, (char*)NULL, 1.0f);
142 susp->spring.packers = GfParmGetNum(hdle, section, PRM_PACKERS, (char*)NULL, 0.0f);
143 susp->damper.bump.C1 = GfParmGetNum(hdle, section, PRM_SLOWBUMP, (char*)NULL, 0.0f);
144 susp->damper.rebound.C1 = GfParmGetNum(hdle, section, PRM_SLOWREBOUND, (char*)NULL, 0.0f);
145 susp->damper.bump.C2 = GfParmGetNum(hdle, section, PRM_FASTBUMP, (char*)NULL, susp->damper.bump.C1);
146 susp->damper.rebound.C2 = GfParmGetNum(hdle, section, PRM_FASTREBOUND, (char*)NULL, susp->damper.rebound.C1);
147 susp->damper.bump.v1 = GfParmGetNum(hdle, section, PRM_BUMPTHRESHOLD, (char*)NULL, 0.5f);
148 susp->damper.rebound.v1 = GfParmGetNum(hdle, section, PRM_REBOUNDTHRESHOLD, (char*)NULL, 0.5f);
149
150 susp->spring.x0 = susp->spring.bellcrank * X0;
151 susp->spring.F0 = F0 / susp->spring.bellcrank;
152 susp->spring.K = - susp->spring.K;
153
154 initDamper(susp);
155 }
156
157
SimSuspReConfig(tCar * car,int index,tSuspension * susp,tdble F0,tdble X0)158 void SimSuspReConfig(tCar* car, int index, tSuspension *susp, tdble F0, tdble X0)
159 {
160 // Spring
161 tCarPitSetupValue* v = &car->carElt->pitcmd.setup.suspspring[index];
162 if (SimAdjustPitCarSetupParam(v)) {
163 susp->spring.K = - v->value;
164 }
165
166 // Packers
167 v = &car->carElt->pitcmd.setup.susppackers[index];
168 if (SimAdjustPitCarSetupParam(v)) {
169 susp->spring.packers = v->value;
170 }
171
172 // Slow bump
173 v = &car->carElt->pitcmd.setup.suspslowbump[index];
174 if (SimAdjustPitCarSetupParam(v)) {
175 susp->damper.bump.C1 = v->value;
176 }
177
178 // Slow rebound
179 v = &car->carElt->pitcmd.setup.suspslowrebound[index];
180 if (SimAdjustPitCarSetupParam(v)) {
181 susp->damper.rebound.C1 = v->value;
182 }
183
184 // Fast bump
185 v = &car->carElt->pitcmd.setup.suspfastbump[index];
186 if (SimAdjustPitCarSetupParam(v)) {
187 susp->damper.bump.C2 = v->value;
188 }
189
190 // Fast rebound
191 v = &car->carElt->pitcmd.setup.suspfastrebound[index];
192 if (SimAdjustPitCarSetupParam(v)) {
193 susp->damper.rebound.C2 = v->value;
194 }
195
196 susp->spring.x0 = susp->spring.bellcrank * X0;
197 susp->spring.F0 = F0 / susp->spring.bellcrank;
198
199 initDamper(susp);
200 }
201
202
SimSuspThirdReConfig(tCar * car,int index,tSuspension * susp,tdble F0,tdble X0)203 void SimSuspThirdReConfig(tCar* car, int index, tSuspension *susp, tdble F0, tdble X0)
204 {
205 // Spring
206 tCarPitSetupValue* v = &car->carElt->pitcmd.setup.thirdspring[index];
207 if (SimAdjustPitCarSetupParam(v)) {
208 susp->spring.K = - v->value;
209 }
210
211 // Bump
212 v = &car->carElt->pitcmd.setup.thirdbump[index];
213 if (SimAdjustPitCarSetupParam(v)) {
214 susp->damper.bump.C1 = v->value;
215 susp->damper.bump.C2 = v->value;
216 }
217
218 // Rebound
219 v = &car->carElt->pitcmd.setup.thirdrebound[index];
220 if (SimAdjustPitCarSetupParam(v)) {
221 susp->damper.rebound.C1 = v->value;
222 susp->damper.rebound.C2 = v->value;
223 }
224
225 susp->spring.xMax = X0;
226
227 susp->spring.x0 = susp->spring.bellcrank * X0;
228 susp->spring.F0 = F0 / susp->spring.bellcrank;
229
230 initDamper(susp);
231 }
232