1 /**********************************************************************
3 FILENAME: uiuc_gear.cpp
5 ----------------------------------------------------------------------
7 DESCRIPTION: determine the gear forces and moments
9 ----------------------------------------------------------------------
13 ----------------------------------------------------------------------
15 REFERENCES: based on c172_gear by Tony Peden and others
17 ----------------------------------------------------------------------
19 HISTORY: 03/09/2001 initial release
21 ----------------------------------------------------------------------
23 AUTHOR(S): David Megginson <david@megginson.com
25 ----------------------------------------------------------------------
29 ----------------------------------------------------------------------
33 ----------------------------------------------------------------------
37 ----------------------------------------------------------------------
39 CALLED BY: uiuc_wrapper.cpp
41 ----------------------------------------------------------------------
45 ----------------------------------------------------------------------
47 COPYRIGHT: (c) 2001 by David Megginson
49 This program is free software; you can redistribute it and/or
50 modify it under the terms of the GNU General Public License
51 as published by the Free Software Foundation.
53 This program is distributed in the hope that it will be useful,
54 but WITHOUT ANY WARRANTY; without even the implied warranty of
55 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
56 GNU General Public License for more details.
58 You should have received a copy of the GNU General Public License
59 along with this program; if not, write to the Free Software
60 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
61 USA or view http://www.gnu.org/copyleft/gpl.html.
63 **********************************************************************/
65 #include <simgear/compiler.h>
67 #include "uiuc_gear.h"
72 #define HEIGHT_AGL_WHEEL d_wheel_rwy_local_v[2]
75 static void sub3( DATA v1[], DATA v2[], DATA result[] )
77 result[0] = v1[0] - v2[0];
78 result[1] = v1[1] - v2[1];
79 result[2] = v1[2] - v2[2];
82 static void add3( DATA v1[], DATA v2[], DATA result[] )
84 result[0] = v1[0] + v2[0];
85 result[1] = v1[1] + v2[1];
86 result[2] = v1[2] + v2[2];
89 static void cross3( DATA v1[], DATA v2[], DATA result[] )
91 result[0] = v1[1]*v2[2] - v1[2]*v2[1];
92 result[1] = v1[2]*v2[0] - v1[0]*v2[2];
93 result[2] = v1[0]*v2[1] - v1[1]*v2[0];
96 static void multtrans3x3by3( DATA m[][3], DATA v[], DATA result[] )
98 result[0] = m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2];
99 result[1] = m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2];
100 result[2] = m[0][2]*v[0] + m[1][2]*v[1] + m[2][2]*v[2];
103 static void mult3x3by3( DATA m[][3], DATA v[], DATA result[] )
105 result[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];
106 result[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];
107 result[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];
110 static void clear3( DATA v[] )
112 v[0] = 0.; v[1] = 0.; v[2] = 0.;
119 * Aircraft specific initializations and data goes here
122 static DATA percent_brake[MAX_GEAR] = /* percent applied braking */
126 0., 0., 0., 0. }; /* 0 = none, 1 = full */
127 static DATA caster_angle_rad[MAX_GEAR] = /* steerable tires - in */
131 0., 0., 0., 0. }; /* radians, +CW */
133 * End of aircraft specific code
137 * Constants & coefficients for tyres on tarmac - ref [1]
140 /* skid function looks like:
146 * sliding_mu | / +------
149 * +--+------------------------>
156 static int it_rolls[MAX_GEAR] =
161 static DATA sliding_mu[MAX_GEAR] =
162 { 0.5, 0.5, 0.5, 0.3,
165 0.3, 0.3, 0.3, 0.3 };
166 static DATA max_brake_mu[MAX_GEAR] =
167 { 0.0, 0.6, 0.6, 0.0,
170 0.0, 0.0, 0.0, 0.0 };
171 static DATA max_mu = 0.8;
172 static DATA bkout_v = 0.1;
173 static DATA skid_v = 1.0;
175 * Local data variables
178 DATA d_wheel_cg_body_v[3]; /* wheel offset from cg, X-Y-Z */
179 DATA d_wheel_cg_local_v[3]; /* wheel offset from cg, N-E-D */
180 DATA d_wheel_rwy_local_v[3]; /* wheel offset from rwy, N-E-U */
181 DATA v_wheel_cg_local_v[3]; /*wheel velocity rel to cg N-E-D*/
182 DATA v_wheel_body_v[3]; /* wheel velocity, X-Y-Z */
183 DATA v_wheel_local_v[3]; /* wheel velocity, N-E-D */
184 DATA f_wheel_local_v[3]; /* wheel reaction force, N-E-D */
185 DATA altitude_local_v[3]; /*altitude vector in local (N-E-D) i.e. (0,0,h)*/
186 DATA altitude_body_v[3]; /*altitude vector in body (X,Y,Z)*/
187 DATA temp3a[3], temp3b[3], tempF[3], tempM[3];
188 DATA reaction_normal_force; /* wheel normal (to rwy) force */
189 DATA cos_wheel_hdg_angle, sin_wheel_hdg_angle; /* temp storage */
190 DATA v_wheel_forward, v_wheel_sideward, abs_v_wheel_sideward;
191 DATA forward_mu, sideward_mu; /* friction coefficients */
192 DATA beta_mu; /* breakout friction slope */
193 DATA forward_wheel_force, sideward_wheel_force;
195 int i; /* per wheel loop counter */
198 * Execution starts here
201 beta_mu = max_mu/(skid_v-bkout_v);
202 clear3( F_gear_v ); /* Initialize sum of forces... */
203 clear3( M_gear_v ); /* ...and moments */
206 * Put aircraft specific executable code here
209 percent_brake[1] = Brake_pct[0];
210 percent_brake[2] = Brake_pct[1];
212 caster_angle_rad[0] =
213 (0.01 + 0.04 * (1 - V_calibrated_kts / 130)) * Rudder_pedal;
216 for (i=0;i<MAX_GEAR;i++) /* Loop for each wheel */
218 // Execute only if the gear has been defined
222 /* printf("%s:\n",gear_strings[i]); */
226 /*========================================*/
227 /* Calculate wheel position w.r.t. runway */
228 /*========================================*/
231 /* printf("\thgcg: %g, theta: %g,phi: %g\n",D_cg_above_rwy,Theta*RAD_TO_DEG,Phi*RAD_TO_DEG); */
234 /* First calculate wheel location w.r.t. cg in body (X-Y-Z) axes... */
236 sub3( D_gear_v[i], D_cg_rp_body_v, d_wheel_cg_body_v );
238 /* then converting to local (North-East-Down) axes... */
240 multtrans3x3by3( T_local_to_body_m, d_wheel_cg_body_v, d_wheel_cg_local_v );
243 /* Runway axes correction - third element is Altitude, not (-)Z... */
245 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* since altitude = -Z */
247 /* Add wheel offset to cg location in local axes */
249 add3( d_wheel_cg_local_v, D_cg_rwy_local_v, d_wheel_rwy_local_v );
251 /* remove Runway axes correction so right hand rule applies */
253 d_wheel_cg_local_v[2] = -d_wheel_cg_local_v[2]; /* now Z positive down */
255 /*============================*/
256 /* Calculate wheel velocities */
257 /*============================*/
259 /* contribution due to angular rates */
261 cross3( Omega_body_v, d_wheel_cg_body_v, temp3a );
263 /* transform into local axes */
265 multtrans3x3by3( T_local_to_body_m, temp3a,v_wheel_cg_local_v );
267 /* plus contribution due to cg velocities */
269 add3( v_wheel_cg_local_v, V_local_rel_ground_v, v_wheel_local_v );
271 clear3(f_wheel_local_v);
272 reaction_normal_force=0;
273 if( HEIGHT_AGL_WHEEL < 0. )
274 /*the wheel is underground -- which implies ground contact
275 so calculate reaction forces */
277 /*===========================================*/
278 /* Calculate forces & moments for this wheel */
279 /*===========================================*/
281 /* Add any anticipation, or frame lead/prediction, here... */
283 /* no lead used at present */
285 /* Calculate sideward and forward velocities of the wheel
286 in the runway plane */
288 cos_wheel_hdg_angle = cos(caster_angle_rad[i] + Psi);
289 sin_wheel_hdg_angle = sin(caster_angle_rad[i] + Psi);
291 v_wheel_forward = v_wheel_local_v[0]*cos_wheel_hdg_angle
292 + v_wheel_local_v[1]*sin_wheel_hdg_angle;
293 v_wheel_sideward = v_wheel_local_v[1]*cos_wheel_hdg_angle
294 - v_wheel_local_v[0]*sin_wheel_hdg_angle;
297 /* Calculate normal load force (simple spring constant) */
299 reaction_normal_force = 0.;
301 reaction_normal_force = kgear[i]*d_wheel_rwy_local_v[2]
302 - v_wheel_local_v[2]*cgear[i];
303 /* printf("\treaction_normal_force: %g\n",reaction_normal_force); */
305 if (reaction_normal_force > 0.) reaction_normal_force = 0.;
306 /* to prevent damping component from swamping spring component */
309 /* Calculate friction coefficients */
313 forward_mu = (max_brake_mu[i] - muGear[i])*percent_brake[i] + muGear[i];
314 abs_v_wheel_sideward = sqrt(v_wheel_sideward*v_wheel_sideward);
315 sideward_mu = sliding_mu[i];
316 if (abs_v_wheel_sideward < skid_v)
317 sideward_mu = (abs_v_wheel_sideward - bkout_v)*beta_mu;
318 if (abs_v_wheel_sideward < bkout_v) sideward_mu = 0.;
322 forward_mu=sliding_mu[i];
323 sideward_mu=sliding_mu[i];
326 /* Calculate foreward and sideward reaction forces */
328 forward_wheel_force = forward_mu*reaction_normal_force;
329 sideward_wheel_force = sideward_mu*reaction_normal_force;
330 if(v_wheel_forward < 0.) forward_wheel_force = -forward_wheel_force;
331 if(v_wheel_sideward < 0.) sideward_wheel_force = -sideward_wheel_force;
332 /* printf("\tFfwdgear: %g Fsidegear: %g\n",forward_wheel_force,sideward_wheel_force);
334 /* Rotate into local (N-E-D) axes */
336 f_wheel_local_v[0] = forward_wheel_force*cos_wheel_hdg_angle
337 - sideward_wheel_force*sin_wheel_hdg_angle;
338 f_wheel_local_v[1] = forward_wheel_force*sin_wheel_hdg_angle
339 + sideward_wheel_force*cos_wheel_hdg_angle;
340 f_wheel_local_v[2] = reaction_normal_force;
342 /* Convert reaction force from local (N-E-D) axes to body (X-Y-Z) */
343 mult3x3by3( T_local_to_body_m, f_wheel_local_v, tempF );
345 /* Calculate moments from force and offsets in body axes */
347 cross3( d_wheel_cg_body_v, tempF, tempM );
349 /* Sum forces and moments across all wheels */
351 add3( tempF, F_gear_v, F_gear_v );
352 add3( tempM, M_gear_v, M_gear_v );
359 /* printf("\tN: %g,dZrwy: %g dZdotrwy: %g\n",reaction_normal_force,HEIGHT_AGL_WHEEL,v_wheel_cg_local_v[2]); */
361 /*printf("\tFxgear: %g Fygear: %g, Fzgear: %g\n",F_X_gear,F_Y_gear,F_Z_gear);
362 printf("\tMgear: %g, Lgear: %g, Ngear: %g\n\n",M_m_gear,M_l_gear,M_n_gear); */
368 // end uiuc_engine.cpp