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.17 2000/09/14 15:36:25 curt
40 Tweaks to ground steering sensitivity.
42 Revision 1.16 2000/09/13 19:51:09 curt
43 MacOS changes by Darrell Walisser.
45 Revision 1.15 2000/06/12 18:52:37 curt
46 Added differential braking (Alex and David).
48 Revision 1.14 2000/04/10 18:09:41 curt
49 David Megginson made a few (mostly minor) mods to the LaRCsim files, and
50 it's now possible to choose the LaRCsim model at runtime, as in
56 fgfs --aircraft=uiuc --aircraft-dir=Aircraft-uiuc/Boeing747
58 I did this so that I could play with the UIUC stuff without losing
59 Tony's C172 with its flaps, etc. I did my best to respect the design
60 of the LaRCsim code by staying in C, making only minimal changes, and
61 not introducing any dependencies on the rest of FlightGear. The
62 modified files are attached.
64 Revision 1.13 1999/12/13 20:43:41 curt
68 ----------------------------------------------------------------------------
72 ----------------------------------------------------------------------------
76 ----------------------------------------------------------------------------
80 ----------------------------------------------------------------------------
84 ----------------------------------------------------------------------------
88 --------------------------------------------------------------------------*/
91 #include "ls_constants.h"
92 #include "ls_generic.h"
93 #include "ls_cockpit.h"
95 #define HEIGHT_AGL_WHEEL d_wheel_rwy_local_v[2]
98 static sub3( DATA v1[], DATA v2[], DATA result[] )
100 result[0] = v1[0] - v2[0];
101 result[1] = v1[1] - v2[1];
102 result[2] = v1[2] - v2[2];
105 static add3( DATA v1[], DATA v2[], DATA result[] )
107 result[0] = v1[0] + v2[0];
108 result[1] = v1[1] + v2[1];
109 result[2] = v1[2] + v2[2];
112 static cross3( DATA v1[], DATA v2[], DATA result[] )
114 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
115 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
116 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
119 static multtrans3x3by3( DATA m[][3], DATA v[], DATA result[] )
121 result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
122 result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
123 result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
126 static mult3x3by3( DATA m[][3], DATA v[], DATA result[] )
128 result[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];
129 result[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];
130 result[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];
133 static clear3( DATA v[] )
135 v[0] = 0.; v[1] = 0.; v[2] = 0.;
140 char rcsid[] = "$Id$";
142 char gear_strings[NUM_WHEELS][12]={"nose","right main", "left main", "tail skid"};
144 * Aircraft specific initializations and data goes here
148 static int num_wheels = NUM_WHEELS; /* number of wheels */
149 static DATA d_wheel_rp_body_v[NUM_WHEELS][3] = /* X, Y, Z locations,full extension */
151 { 3.91, 0., 6.67 }, /*nose*/ /* in feet */
152 { -1.47, 3.58, 6.71 }, /*right main*/
153 { -1.47, -3.58, 6.71 }, /*left main*/
154 { -15.67, 0, 2.42 } /*tail skid */
156 static DATA gear_travel[NUM_WHEELS] = /*in Z-axis*/
157 { -0.5, 2.5, 2.5, 0};
158 static DATA spring_constant[NUM_WHEELS] = /* springiness, lbs/ft */
159 { 1200., 900., 900., 10000. };
160 static DATA spring_damping[NUM_WHEELS] = /* damping, lbs/ft/sec */
161 { 200., 300., 300., 400. };
162 static DATA percent_brake[NUM_WHEELS] = /* percent applied braking */
163 { 0., 0., 0., 0. }; /* 0 = none, 1 = full */
164 static DATA caster_angle_rad[NUM_WHEELS] = /* steerable tires - in */
165 { 0., 0., 0., 0}; /* radians, +CW */
167 * End of aircraft specific code
171 * Constants & coefficients for tyres on tarmac - ref [1]
174 /* skid function looks like:
180 * sliding_mu | / +------
183 * +--+------------------------>
190 static int it_rolls[NUM_WHEELS] = { 1,1,1,0};
191 static DATA sliding_mu[NUM_WHEELS] = { 0.5, 0.5, 0.5, 0.3};
192 static DATA rolling_mu[NUM_WHEELS] = { 0.01, 0.01, 0.01, 0.0};
193 static DATA max_brake_mu[NUM_WHEELS] ={ 0.0, 0.6, 0.6, 0.0};
194 static DATA max_mu = 0.8;
195 static DATA bkout_v = 0.1;
196 static DATA skid_v = 1.0;
198 * Local data variables
201 DATA d_wheel_cg_body_v[3]; /* wheel offset from cg, X-Y-Z */
202 DATA d_wheel_cg_local_v[3]; /* wheel offset from cg, N-E-D */
203 DATA d_wheel_rwy_local_v[3]; /* wheel offset from rwy, N-E-U */
204 DATA v_wheel_cg_local_v[3]; /*wheel velocity rel to cg N-E-D*/
205 DATA v_wheel_body_v[3]; /* wheel velocity, X-Y-Z */
206 DATA v_wheel_local_v[3]; /* wheel velocity, N-E-D */
207 DATA f_wheel_local_v[3]; /* wheel reaction force, N-E-D */
208 DATA altitude_local_v[3]; /*altitude vector in local (N-E-D) i.e. (0,0,h)*/
209 DATA altitude_body_v[3]; /*altitude vector in body (X,Y,Z)*/
210 DATA temp3a[3], temp3b[3], tempF[3], tempM[3];
211 DATA reaction_normal_force; /* wheel normal (to rwy) force */
212 DATA cos_wheel_hdg_angle, sin_wheel_hdg_angle; /* temp storage */
213 DATA v_wheel_forward, v_wheel_sideward, abs_v_wheel_sideward;
214 DATA forward_mu, sideward_mu; /* friction coefficients */
215 DATA beta_mu; /* breakout friction slope */
216 DATA forward_wheel_force, sideward_wheel_force;
218 int i; /* per wheel loop counter */
221 * Execution starts here
224 beta_mu = max_mu/(skid_v-bkout_v);
225 clear3( F_gear_v ); /* Initialize sum of forces... */
226 clear3( M_gear_v ); /* ...and moments */
229 * Put aircraft specific executable code here
232 percent_brake[1] = Brake_pct[0];
233 percent_brake[2] = Brake_pct[1];
235 caster_angle_rad[0] =
236 (0.01 + 0.04 * (1 - V_calibrated_kts / 130)) * Rudder_pedal;
239 for (i=0;i<num_wheels;i++) /* Loop for each wheel */
241 /* printf("%s:\n",gear_strings[i]); */
245 /*========================================*/
246 /* Calculate wheel position w.r.t. runway */
247 /*========================================*/
250 /* printf("\thgcg: %g, theta: %g,phi: %g\n",D_cg_above_rwy,Theta*RAD_TO_DEG,Phi*RAD_TO_DEG); */
253 /* First calculate wheel location w.r.t. cg in body (X-Y-Z) axes... */
255 sub3( d_wheel_rp_body_v[i], D_cg_rp_body_v, d_wheel_cg_body_v );
257 /* then converting to local (North-East-Down) axes... */
259 multtrans3x3by3( T_local_to_body_m, d_wheel_cg_body_v, d_wheel_cg_local_v );
262 /* Runway axes correction - third element is Altitude, not (-)Z... */
264 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* since altitude = -Z */
266 /* Add wheel offset to cg location in local axes */
268 add3( d_wheel_cg_local_v, D_cg_rwy_local_v, d_wheel_rwy_local_v );
270 /* remove Runway axes correction so right hand rule applies */
272 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* now Z positive down */
274 /*============================*/
275 /* Calculate wheel velocities */
276 /*============================*/
278 /* contribution due to angular rates */
280 cross3( Omega_body_v, d_wheel_cg_body_v, temp3a );
282 /* transform into local axes */
284 multtrans3x3by3( T_local_to_body_m, temp3a,v_wheel_cg_local_v );
286 /* plus contribution due to cg velocities */
288 add3( v_wheel_cg_local_v, V_local_rel_ground_v, v_wheel_local_v );
290 clear3(f_wheel_local_v);
291 reaction_normal_force=0;
292 if( HEIGHT_AGL_WHEEL < 0. )
293 /*the wheel is underground -- which implies ground contact
294 so calculate reaction forces */
296 /*===========================================*/
297 /* Calculate forces & moments for this wheel */
298 /*===========================================*/
300 /* Add any anticipation, or frame lead/prediction, here... */
302 /* no lead used at present */
304 /* Calculate sideward and forward velocities of the wheel
305 in the runway plane */
307 cos_wheel_hdg_angle = cos(caster_angle_rad[i] + Psi);
308 sin_wheel_hdg_angle = sin(caster_angle_rad[i] + Psi);
310 v_wheel_forward = v_wheel_local_v[0]*cos_wheel_hdg_angle
311 + v_wheel_local_v[1]*sin_wheel_hdg_angle;
312 v_wheel_sideward = v_wheel_local_v[1]*cos_wheel_hdg_angle
313 - v_wheel_local_v[0]*sin_wheel_hdg_angle;
316 /* Calculate normal load force (simple spring constant) */
318 reaction_normal_force = 0.;
320 reaction_normal_force = spring_constant[i]*d_wheel_rwy_local_v[2]
321 - v_wheel_local_v[2]*spring_damping[i];
322 /* printf("\treaction_normal_force: %g\n",reaction_normal_force); */
324 if (reaction_normal_force > 0.) reaction_normal_force = 0.;
325 /* to prevent damping component from swamping spring component */
328 /* Calculate friction coefficients */
332 forward_mu = (max_brake_mu[i] - rolling_mu[i])*percent_brake[i] + rolling_mu[i];
333 abs_v_wheel_sideward = sqrt(v_wheel_sideward*v_wheel_sideward);
334 sideward_mu = sliding_mu[i];
335 if (abs_v_wheel_sideward < skid_v)
336 sideward_mu = (abs_v_wheel_sideward - bkout_v)*beta_mu;
337 if (abs_v_wheel_sideward < bkout_v) sideward_mu = 0.;
341 forward_mu=sliding_mu[i];
342 sideward_mu=sliding_mu[i];
345 /* Calculate foreward and sideward reaction forces */
347 forward_wheel_force = forward_mu*reaction_normal_force;
348 sideward_wheel_force = sideward_mu*reaction_normal_force;
349 if(v_wheel_forward < 0.) forward_wheel_force = -forward_wheel_force;
350 if(v_wheel_sideward < 0.) sideward_wheel_force = -sideward_wheel_force;
351 /* printf("\tFfwdgear: %g Fsidegear: %g\n",forward_wheel_force,sideward_wheel_force);
353 /* Rotate into local (N-E-D) axes */
355 f_wheel_local_v[0] = forward_wheel_force*cos_wheel_hdg_angle
356 - sideward_wheel_force*sin_wheel_hdg_angle;
357 f_wheel_local_v[1] = forward_wheel_force*sin_wheel_hdg_angle
358 + sideward_wheel_force*cos_wheel_hdg_angle;
359 f_wheel_local_v[2] = reaction_normal_force;
361 /* Convert reaction force from local (N-E-D) axes to body (X-Y-Z) */
362 mult3x3by3( T_local_to_body_m, f_wheel_local_v, tempF );
364 /* Calculate moments from force and offsets in body axes */
366 cross3( d_wheel_cg_body_v, tempF, tempM );
368 /* Sum forces and moments across all wheels */
370 add3( tempF, F_gear_v, F_gear_v );
371 add3( tempM, M_gear_v, M_gear_v );
378 /* printf("\tN: %g,dZrwy: %g dZdotrwy: %g\n",reaction_normal_force,HEIGHT_AGL_WHEEL,v_wheel_cg_local_v[2]); */
380 /*printf("\tFxgear: %g Fygear: %g, Fzgear: %g\n",F_X_gear,F_Y_gear,F_Z_gear);
381 printf("\tMgear: %g, Lgear: %g, Ngear: %g\n\n",M_m_gear,M_l_gear,M_n_gear); */