1 /***************************************************************************
5 ----------------------------------------------------------------------------
7 FUNCTION: Landing gear model for example simulation
9 ----------------------------------------------------------------------------
11 MODULE STATUS: developmental
13 ----------------------------------------------------------------------------
15 GENEALOGY: Created 931012 by E. B. Jackson
17 ----------------------------------------------------------------------------
19 DESIGNED BY: E. B. Jackson
21 CODED BY: E. B. Jackson
23 MAINTAINED BY: E. B. Jackson
25 ----------------------------------------------------------------------------
31 931218 Added navion.h header to allow connection with
32 aileron displacement for nosewheel steering. EBJ
33 940511 Connected nosewheel to rudder pedal; adjusted gain.
39 Revision 1.19 2001/03/02 21:37:01 curt
40 Added a first pass at a C++ sound manager class.
42 Revision 1.18 2000/12/13 22:02:02 curt
43 MacOS changes contributed by Darrell Walisser (12/13/2000)
45 Revision 1.17 2000/09/14 15:36:25 curt
46 Tweaks to ground steering sensitivity.
48 Revision 1.16 2000/09/13 19:51:09 curt
49 MacOS changes by Darrell Walisser.
51 Revision 1.15 2000/06/12 18:52:37 curt
52 Added differential braking (Alex and David).
54 Revision 1.14 2000/04/10 18:09:41 curt
55 David Megginson made a few (mostly minor) mods to the LaRCsim files, and
56 it's now possible to choose the LaRCsim model at runtime, as in
62 fgfs --aircraft=uiuc --aircraft-dir=Aircraft-uiuc/Boeing747
64 I did this so that I could play with the UIUC stuff without losing
65 Tony's C172 with its flaps, etc. I did my best to respect the design
66 of the LaRCsim code by staying in C, making only minimal changes, and
67 not introducing any dependencies on the rest of FlightGear. The
68 modified files are attached.
70 Revision 1.13 1999/12/13 20:43:41 curt
74 ----------------------------------------------------------------------------
78 ----------------------------------------------------------------------------
82 ----------------------------------------------------------------------------
86 ----------------------------------------------------------------------------
90 ----------------------------------------------------------------------------
94 --------------------------------------------------------------------------*/
97 #include "ls_constants.h"
98 #include "ls_generic.h"
99 #include "ls_cockpit.h"
101 #define HEIGHT_AGL_WHEEL d_wheel_rwy_local_v[2]
104 static void sub3( DATA v1[], DATA v2[], DATA result[] )
106 result[0] = v1[0] - v2[0];
107 result[1] = v1[1] - v2[1];
108 result[2] = v1[2] - v2[2];
111 static void add3( DATA v1[], DATA v2[], DATA result[] )
113 result[0] = v1[0] + v2[0];
114 result[1] = v1[1] + v2[1];
115 result[2] = v1[2] + v2[2];
118 static void cross3( DATA v1[], DATA v2[], DATA result[] )
120 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
121 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
122 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
125 static void multtrans3x3by3( DATA m[][3], DATA v[], DATA result[] )
127 result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
128 result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
129 result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
132 static void mult3x3by3( DATA m[][3], DATA v[], DATA result[] )
134 result[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];
135 result[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];
136 result[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];
139 static void clear3( DATA v[] )
141 v[0] = 0.; v[1] = 0.; v[2] = 0.;
146 char rcsid[] = "$Id$";
148 char gear_strings[NUM_WHEELS][12]={"nose","right main", "left main", "tail skid"};
150 * Aircraft specific initializations and data goes here
154 static int num_wheels = NUM_WHEELS; /* number of wheels */
155 static DATA d_wheel_rp_body_v[NUM_WHEELS][3] = /* X, Y, Z locations,full extension */
157 { 3.91, 0., 6.67 }, /*nose*/ /* in feet */
158 { -1.47, 3.58, 6.71 }, /*right main*/
159 { -1.47, -3.58, 6.71 }, /*left main*/
160 { -15.67, 0, 2.42 } /*tail skid */
162 static DATA gear_travel[NUM_WHEELS] = /*in Z-axis*/
163 { -0.5, 2.5, 2.5, 0};
164 static DATA spring_constant[NUM_WHEELS] = /* springiness, lbs/ft */
165 { 1200., 900., 900., 10000. };
166 static DATA spring_damping[NUM_WHEELS] = /* damping, lbs/ft/sec */
167 { 200., 300., 300., 400. };
168 static DATA percent_brake[NUM_WHEELS] = /* percent applied braking */
169 { 0., 0., 0., 0. }; /* 0 = none, 1 = full */
170 static DATA caster_angle_rad[NUM_WHEELS] = /* steerable tires - in */
171 { 0., 0., 0., 0}; /* radians, +CW */
173 * End of aircraft specific code
177 * Constants & coefficients for tyres on tarmac - ref [1]
180 /* skid function looks like:
186 * sliding_mu | / +------
189 * +--+------------------------>
196 static int it_rolls[NUM_WHEELS] = { 1,1,1,0};
197 static DATA sliding_mu[NUM_WHEELS] = { 0.5, 0.5, 0.5, 0.3};
198 static DATA rolling_mu[NUM_WHEELS] = { 0.01, 0.01, 0.01, 0.0};
199 static DATA max_brake_mu[NUM_WHEELS] ={ 0.0, 0.6, 0.6, 0.0};
200 static DATA max_mu = 0.8;
201 static DATA bkout_v = 0.1;
202 static DATA skid_v = 1.0;
204 * Local data variables
207 DATA d_wheel_cg_body_v[3]; /* wheel offset from cg, X-Y-Z */
208 DATA d_wheel_cg_local_v[3]; /* wheel offset from cg, N-E-D */
209 DATA d_wheel_rwy_local_v[3]; /* wheel offset from rwy, N-E-U */
210 DATA v_wheel_cg_local_v[3]; /*wheel velocity rel to cg N-E-D*/
211 DATA v_wheel_body_v[3]; /* wheel velocity, X-Y-Z */
212 DATA v_wheel_local_v[3]; /* wheel velocity, N-E-D */
213 DATA f_wheel_local_v[3]; /* wheel reaction force, N-E-D */
214 DATA altitude_local_v[3]; /*altitude vector in local (N-E-D) i.e. (0,0,h)*/
215 DATA altitude_body_v[3]; /*altitude vector in body (X,Y,Z)*/
216 DATA temp3a[3], temp3b[3], tempF[3], tempM[3];
217 DATA reaction_normal_force; /* wheel normal (to rwy) force */
218 DATA cos_wheel_hdg_angle, sin_wheel_hdg_angle; /* temp storage */
219 DATA v_wheel_forward, v_wheel_sideward, abs_v_wheel_sideward;
220 DATA forward_mu, sideward_mu; /* friction coefficients */
221 DATA beta_mu; /* breakout friction slope */
222 DATA forward_wheel_force, sideward_wheel_force;
224 int i; /* per wheel loop counter */
227 * Execution starts here
230 beta_mu = max_mu/(skid_v-bkout_v);
231 clear3( F_gear_v ); /* Initialize sum of forces... */
232 clear3( M_gear_v ); /* ...and moments */
235 * Put aircraft specific executable code here
238 percent_brake[1] = Brake_pct[0];
239 percent_brake[2] = Brake_pct[1];
241 caster_angle_rad[0] =
242 (0.01 + 0.04 * (1 - V_calibrated_kts / 130)) * Rudder_pedal;
245 for (i=0;i<num_wheels;i++) /* Loop for each wheel */
247 /* printf("%s:\n",gear_strings[i]); */
251 /*========================================*/
252 /* Calculate wheel position w.r.t. runway */
253 /*========================================*/
256 /* printf("\thgcg: %g, theta: %g,phi: %g\n",D_cg_above_rwy,Theta*RAD_TO_DEG,Phi*RAD_TO_DEG); */
259 /* First calculate wheel location w.r.t. cg in body (X-Y-Z) axes... */
261 sub3( d_wheel_rp_body_v[i], D_cg_rp_body_v, d_wheel_cg_body_v );
263 /* then converting to local (North-East-Down) axes... */
265 multtrans3x3by3( T_local_to_body_m, d_wheel_cg_body_v, d_wheel_cg_local_v );
268 /* Runway axes correction - third element is Altitude, not (-)Z... */
270 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* since altitude = -Z */
272 /* Add wheel offset to cg location in local axes */
274 add3( d_wheel_cg_local_v, D_cg_rwy_local_v, d_wheel_rwy_local_v );
276 /* remove Runway axes correction so right hand rule applies */
278 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* now Z positive down */
280 /*============================*/
281 /* Calculate wheel velocities */
282 /*============================*/
284 /* contribution due to angular rates */
286 cross3( Omega_body_v, d_wheel_cg_body_v, temp3a );
288 /* transform into local axes */
290 multtrans3x3by3( T_local_to_body_m, temp3a,v_wheel_cg_local_v );
292 /* plus contribution due to cg velocities */
294 add3( v_wheel_cg_local_v, V_local_rel_ground_v, v_wheel_local_v );
296 clear3(f_wheel_local_v);
297 reaction_normal_force=0;
298 if( HEIGHT_AGL_WHEEL < 0. )
299 /*the wheel is underground -- which implies ground contact
300 so calculate reaction forces */
302 /*===========================================*/
303 /* Calculate forces & moments for this wheel */
304 /*===========================================*/
306 /* Add any anticipation, or frame lead/prediction, here... */
308 /* no lead used at present */
310 /* Calculate sideward and forward velocities of the wheel
311 in the runway plane */
313 cos_wheel_hdg_angle = cos(caster_angle_rad[i] + Psi);
314 sin_wheel_hdg_angle = sin(caster_angle_rad[i] + Psi);
316 v_wheel_forward = v_wheel_local_v[0]*cos_wheel_hdg_angle
317 + v_wheel_local_v[1]*sin_wheel_hdg_angle;
318 v_wheel_sideward = v_wheel_local_v[1]*cos_wheel_hdg_angle
319 - v_wheel_local_v[0]*sin_wheel_hdg_angle;
322 /* Calculate normal load force (simple spring constant) */
324 reaction_normal_force = 0.;
326 reaction_normal_force = spring_constant[i]*d_wheel_rwy_local_v[2]
327 - v_wheel_local_v[2]*spring_damping[i];
328 /* printf("\treaction_normal_force: %g\n",reaction_normal_force); */
330 if (reaction_normal_force > 0.) reaction_normal_force = 0.;
331 /* to prevent damping component from swamping spring component */
334 /* Calculate friction coefficients */
338 forward_mu = (max_brake_mu[i] - rolling_mu[i])*percent_brake[i] + rolling_mu[i];
339 abs_v_wheel_sideward = sqrt(v_wheel_sideward*v_wheel_sideward);
340 sideward_mu = sliding_mu[i];
341 if (abs_v_wheel_sideward < skid_v)
342 sideward_mu = (abs_v_wheel_sideward - bkout_v)*beta_mu;
343 if (abs_v_wheel_sideward < bkout_v) sideward_mu = 0.;
347 forward_mu=sliding_mu[i];
348 sideward_mu=sliding_mu[i];
351 /* Calculate foreward and sideward reaction forces */
353 forward_wheel_force = forward_mu*reaction_normal_force;
354 sideward_wheel_force = sideward_mu*reaction_normal_force;
355 if(v_wheel_forward < 0.) forward_wheel_force = -forward_wheel_force;
356 if(v_wheel_sideward < 0.) sideward_wheel_force = -sideward_wheel_force;
357 /* printf("\tFfwdgear: %g Fsidegear: %g\n",forward_wheel_force,sideward_wheel_force);
359 /* Rotate into local (N-E-D) axes */
361 f_wheel_local_v[0] = forward_wheel_force*cos_wheel_hdg_angle
362 - sideward_wheel_force*sin_wheel_hdg_angle;
363 f_wheel_local_v[1] = forward_wheel_force*sin_wheel_hdg_angle
364 + sideward_wheel_force*cos_wheel_hdg_angle;
365 f_wheel_local_v[2] = reaction_normal_force;
367 /* Convert reaction force from local (N-E-D) axes to body (X-Y-Z) */
368 mult3x3by3( T_local_to_body_m, f_wheel_local_v, tempF );
370 /* Calculate moments from force and offsets in body axes */
372 cross3( d_wheel_cg_body_v, tempF, tempM );
374 /* Sum forces and moments across all wheels */
376 add3( tempF, F_gear_v, F_gear_v );
377 add3( tempM, M_gear_v, M_gear_v );
384 /* printf("\tN: %g,dZrwy: %g dZdotrwy: %g\n",reaction_normal_force,HEIGHT_AGL_WHEEL,v_wheel_cg_local_v[2]); */
386 /*printf("\tFxgear: %g Fygear: %g, Fzgear: %g\n",F_X_gear,F_Y_gear,F_Z_gear);
387 printf("\tMgear: %g, Lgear: %g, Ngear: %g\n\n",M_m_gear,M_l_gear,M_n_gear); */