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.18 2000/12/13 22:02:02 curt
40 MacOS changes contributed by Darrell Walisser (12/13/2000)
42 Revision 1.17 2000/09/14 15:36:25 curt
43 Tweaks to ground steering sensitivity.
45 Revision 1.16 2000/09/13 19:51:09 curt
46 MacOS changes by Darrell Walisser.
48 Revision 1.15 2000/06/12 18:52:37 curt
49 Added differential braking (Alex and David).
51 Revision 1.14 2000/04/10 18:09:41 curt
52 David Megginson made a few (mostly minor) mods to the LaRCsim files, and
53 it's now possible to choose the LaRCsim model at runtime, as in
59 fgfs --aircraft=uiuc --aircraft-dir=Aircraft-uiuc/Boeing747
61 I did this so that I could play with the UIUC stuff without losing
62 Tony's C172 with its flaps, etc. I did my best to respect the design
63 of the LaRCsim code by staying in C, making only minimal changes, and
64 not introducing any dependencies on the rest of FlightGear. The
65 modified files are attached.
67 Revision 1.13 1999/12/13 20:43:41 curt
71 ----------------------------------------------------------------------------
75 ----------------------------------------------------------------------------
79 ----------------------------------------------------------------------------
83 ----------------------------------------------------------------------------
87 ----------------------------------------------------------------------------
91 --------------------------------------------------------------------------*/
94 #include "ls_constants.h"
95 #include "ls_generic.h"
96 #include "ls_cockpit.h"
98 #define HEIGHT_AGL_WHEEL d_wheel_rwy_local_v[2]
101 static void sub3( DATA v1[], DATA v2[], DATA result[] )
103 result[0] = v1[0] - v2[0];
104 result[1] = v1[1] - v2[1];
105 result[2] = v1[2] - v2[2];
108 static void add3( DATA v1[], DATA v2[], DATA result[] )
110 result[0] = v1[0] + v2[0];
111 result[1] = v1[1] + v2[1];
112 result[2] = v1[2] + v2[2];
115 static void cross3( DATA v1[], DATA v2[], DATA result[] )
117 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
118 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
119 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
122 static void multtrans3x3by3( DATA m[][3], DATA v[], DATA result[] )
124 result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
125 result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
126 result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
129 static void mult3x3by3( DATA m[][3], DATA v[], DATA result[] )
131 result[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];
132 result[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];
133 result[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];
136 static void clear3( DATA v[] )
138 v[0] = 0.; v[1] = 0.; v[2] = 0.;
143 char rcsid[] = "$Id$";
145 char gear_strings[NUM_WHEELS][12]={"nose","right main", "left main", "tail skid"};
147 * Aircraft specific initializations and data goes here
151 static int num_wheels = NUM_WHEELS; /* number of wheels */
152 static DATA d_wheel_rp_body_v[NUM_WHEELS][3] = /* X, Y, Z locations,full extension */
154 { 3.91, 0., 6.67 }, /*nose*/ /* in feet */
155 { -1.47, 3.58, 6.71 }, /*right main*/
156 { -1.47, -3.58, 6.71 }, /*left main*/
157 { -15.67, 0, 2.42 } /*tail skid */
159 static DATA gear_travel[NUM_WHEELS] = /*in Z-axis*/
160 { -0.5, 2.5, 2.5, 0};
161 static DATA spring_constant[NUM_WHEELS] = /* springiness, lbs/ft */
162 { 1200., 900., 900., 10000. };
163 static DATA spring_damping[NUM_WHEELS] = /* damping, lbs/ft/sec */
164 { 200., 300., 300., 400. };
165 static DATA percent_brake[NUM_WHEELS] = /* percent applied braking */
166 { 0., 0., 0., 0. }; /* 0 = none, 1 = full */
167 static DATA caster_angle_rad[NUM_WHEELS] = /* steerable tires - in */
168 { 0., 0., 0., 0}; /* radians, +CW */
170 * End of aircraft specific code
174 * Constants & coefficients for tyres on tarmac - ref [1]
177 /* skid function looks like:
183 * sliding_mu | / +------
186 * +--+------------------------>
193 static int it_rolls[NUM_WHEELS] = { 1,1,1,0};
194 static DATA sliding_mu[NUM_WHEELS] = { 0.5, 0.5, 0.5, 0.3};
195 static DATA rolling_mu[NUM_WHEELS] = { 0.01, 0.01, 0.01, 0.0};
196 static DATA max_brake_mu[NUM_WHEELS] ={ 0.0, 0.6, 0.6, 0.0};
197 static DATA max_mu = 0.8;
198 static DATA bkout_v = 0.1;
199 static DATA skid_v = 1.0;
201 * Local data variables
204 DATA d_wheel_cg_body_v[3]; /* wheel offset from cg, X-Y-Z */
205 DATA d_wheel_cg_local_v[3]; /* wheel offset from cg, N-E-D */
206 DATA d_wheel_rwy_local_v[3]; /* wheel offset from rwy, N-E-U */
207 DATA v_wheel_cg_local_v[3]; /*wheel velocity rel to cg N-E-D*/
208 DATA v_wheel_body_v[3]; /* wheel velocity, X-Y-Z */
209 DATA v_wheel_local_v[3]; /* wheel velocity, N-E-D */
210 DATA f_wheel_local_v[3]; /* wheel reaction force, N-E-D */
211 DATA altitude_local_v[3]; /*altitude vector in local (N-E-D) i.e. (0,0,h)*/
212 DATA altitude_body_v[3]; /*altitude vector in body (X,Y,Z)*/
213 DATA temp3a[3], temp3b[3], tempF[3], tempM[3];
214 DATA reaction_normal_force; /* wheel normal (to rwy) force */
215 DATA cos_wheel_hdg_angle, sin_wheel_hdg_angle; /* temp storage */
216 DATA v_wheel_forward, v_wheel_sideward, abs_v_wheel_sideward;
217 DATA forward_mu, sideward_mu; /* friction coefficients */
218 DATA beta_mu; /* breakout friction slope */
219 DATA forward_wheel_force, sideward_wheel_force;
221 int i; /* per wheel loop counter */
224 * Execution starts here
227 beta_mu = max_mu/(skid_v-bkout_v);
228 clear3( F_gear_v ); /* Initialize sum of forces... */
229 clear3( M_gear_v ); /* ...and moments */
232 * Put aircraft specific executable code here
235 percent_brake[1] = Brake_pct[0];
236 percent_brake[2] = Brake_pct[1];
238 caster_angle_rad[0] =
239 (0.01 + 0.04 * (1 - V_calibrated_kts / 130)) * Rudder_pedal;
242 for (i=0;i<num_wheels;i++) /* Loop for each wheel */
244 /* printf("%s:\n",gear_strings[i]); */
248 /*========================================*/
249 /* Calculate wheel position w.r.t. runway */
250 /*========================================*/
253 /* printf("\thgcg: %g, theta: %g,phi: %g\n",D_cg_above_rwy,Theta*RAD_TO_DEG,Phi*RAD_TO_DEG); */
256 /* First calculate wheel location w.r.t. cg in body (X-Y-Z) axes... */
258 sub3( d_wheel_rp_body_v[i], D_cg_rp_body_v, d_wheel_cg_body_v );
260 /* then converting to local (North-East-Down) axes... */
262 multtrans3x3by3( T_local_to_body_m, d_wheel_cg_body_v, d_wheel_cg_local_v );
265 /* Runway axes correction - third element is Altitude, not (-)Z... */
267 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* since altitude = -Z */
269 /* Add wheel offset to cg location in local axes */
271 add3( d_wheel_cg_local_v, D_cg_rwy_local_v, d_wheel_rwy_local_v );
273 /* remove Runway axes correction so right hand rule applies */
275 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* now Z positive down */
277 /*============================*/
278 /* Calculate wheel velocities */
279 /*============================*/
281 /* contribution due to angular rates */
283 cross3( Omega_body_v, d_wheel_cg_body_v, temp3a );
285 /* transform into local axes */
287 multtrans3x3by3( T_local_to_body_m, temp3a,v_wheel_cg_local_v );
289 /* plus contribution due to cg velocities */
291 add3( v_wheel_cg_local_v, V_local_rel_ground_v, v_wheel_local_v );
293 clear3(f_wheel_local_v);
294 reaction_normal_force=0;
295 if( HEIGHT_AGL_WHEEL < 0. )
296 /*the wheel is underground -- which implies ground contact
297 so calculate reaction forces */
299 /*===========================================*/
300 /* Calculate forces & moments for this wheel */
301 /*===========================================*/
303 /* Add any anticipation, or frame lead/prediction, here... */
305 /* no lead used at present */
307 /* Calculate sideward and forward velocities of the wheel
308 in the runway plane */
310 cos_wheel_hdg_angle = cos(caster_angle_rad[i] + Psi);
311 sin_wheel_hdg_angle = sin(caster_angle_rad[i] + Psi);
313 v_wheel_forward = v_wheel_local_v[0]*cos_wheel_hdg_angle
314 + v_wheel_local_v[1]*sin_wheel_hdg_angle;
315 v_wheel_sideward = v_wheel_local_v[1]*cos_wheel_hdg_angle
316 - v_wheel_local_v[0]*sin_wheel_hdg_angle;
319 /* Calculate normal load force (simple spring constant) */
321 reaction_normal_force = 0.;
323 reaction_normal_force = spring_constant[i]*d_wheel_rwy_local_v[2]
324 - v_wheel_local_v[2]*spring_damping[i];
325 /* printf("\treaction_normal_force: %g\n",reaction_normal_force); */
327 if (reaction_normal_force > 0.) reaction_normal_force = 0.;
328 /* to prevent damping component from swamping spring component */
331 /* Calculate friction coefficients */
335 forward_mu = (max_brake_mu[i] - rolling_mu[i])*percent_brake[i] + rolling_mu[i];
336 abs_v_wheel_sideward = sqrt(v_wheel_sideward*v_wheel_sideward);
337 sideward_mu = sliding_mu[i];
338 if (abs_v_wheel_sideward < skid_v)
339 sideward_mu = (abs_v_wheel_sideward - bkout_v)*beta_mu;
340 if (abs_v_wheel_sideward < bkout_v) sideward_mu = 0.;
344 forward_mu=sliding_mu[i];
345 sideward_mu=sliding_mu[i];
348 /* Calculate foreward and sideward reaction forces */
350 forward_wheel_force = forward_mu*reaction_normal_force;
351 sideward_wheel_force = sideward_mu*reaction_normal_force;
352 if(v_wheel_forward < 0.) forward_wheel_force = -forward_wheel_force;
353 if(v_wheel_sideward < 0.) sideward_wheel_force = -sideward_wheel_force;
354 /* printf("\tFfwdgear: %g Fsidegear: %g\n",forward_wheel_force,sideward_wheel_force);
356 /* Rotate into local (N-E-D) axes */
358 f_wheel_local_v[0] = forward_wheel_force*cos_wheel_hdg_angle
359 - sideward_wheel_force*sin_wheel_hdg_angle;
360 f_wheel_local_v[1] = forward_wheel_force*sin_wheel_hdg_angle
361 + sideward_wheel_force*cos_wheel_hdg_angle;
362 f_wheel_local_v[2] = reaction_normal_force;
364 /* Convert reaction force from local (N-E-D) axes to body (X-Y-Z) */
365 mult3x3by3( T_local_to_body_m, f_wheel_local_v, tempF );
367 /* Calculate moments from force and offsets in body axes */
369 cross3( d_wheel_cg_body_v, tempF, tempM );
371 /* Sum forces and moments across all wheels */
373 add3( tempF, F_gear_v, F_gear_v );
374 add3( tempM, M_gear_v, M_gear_v );
381 /* printf("\tN: %g,dZrwy: %g dZdotrwy: %g\n",reaction_normal_force,HEIGHT_AGL_WHEEL,v_wheel_cg_local_v[2]); */
383 /*printf("\tFxgear: %g Fygear: %g, Fzgear: %g\n",F_X_gear,F_Y_gear,F_Z_gear);
384 printf("\tMgear: %g, Lgear: %g, Ngear: %g\n\n",M_m_gear,M_l_gear,M_n_gear); */