1 /***************************************************************************
5 ----------------------------------------------------------------------------
7 FUNCTION: aerodynamics model based on constant stability derivatives
9 ----------------------------------------------------------------------------
11 MODULE STATUS: developmental
13 ----------------------------------------------------------------------------
15 GENEALOGY: Based on data from:
16 Part 1 of Roskam's S&C text
17 The FAA type certificate data sheet for the 172
18 Various sources on the net
19 John D. Anderson's Intro to Flight text (NACA 2412 data)
20 UIUC's airfoil data web site
22 ----------------------------------------------------------------------------
24 DESIGNED BY: Tony Peden
28 MAINTAINED BY: Tony Peden
30 ----------------------------------------------------------------------------
35 6/10/99 Initial test release
38 ----------------------------------------------------------------------------
48 Croll,Cl rolling moment (yeah, I know. Shoot me.)
51 o constant i.e. not a function of alpha or beta
60 de elevator deflection
67 ----------------------------------------------------------------------------
71 ----------------------------------------------------------------------------
75 ----------------------------------------------------------------------------
79 ----------------------------------------------------------------------------
83 --------------------------------------------------------------------------*/
87 #include "ls_generic.h"
88 #include "ls_cockpit.h"
89 #include "ls_constants.h"
91 #include "c172_aero.h"
99 #define DYN_ON_SPEED 33 /*20 knots*/
103 #define NZ generic_.n_cg_body_v[2]
109 extern COCKPIT cockpit_;
112 SCALAR interp(SCALAR *y_table, SCALAR *x_table, int Ntable, SCALAR x)
119 /* if x is outside the table, return value at x[0] or x[Ntable-1]*/
123 /* printf("x smaller than x_table[0]: %g %g\n",x,x_table[0]); */
125 else if(x >= x_table[Ntable-1])
127 slope=(y_table[Ntable-1]-y_table[Ntable-2])/(x_table[Ntable-1]-x_table[Ntable-2]);
128 y=slope*(x-x_table[Ntable-1]) +y_table[Ntable-1];
130 /* printf("x larger than x_table[N]: %g %g %d\n",x,x_table[NCL-1],Ntable-1);
132 else /*x is within the table, interpolate linearly to find y value*/
135 while(x_table[i] <= x) {i++;}
136 slope=(y_table[i]-y_table[i-1])/(x_table[i]-x_table[i-1]);
137 /* printf("x: %g, i: %d, cl[i]: %g, cl[i-1]: %g, slope: %g\n",x,i,y_table[i],y_table[i-1],slope); */
138 y=slope*(x-x_table[i-1]) +y_table[i-1];
144 void aero( SCALAR dt, int Initialize ) {
148 static int flap_dir=0;
149 static SCALAR lastFlapHandle=0;
151 static SCALAR trim_inc = 0.0002;
153 static SCALAR alpha_ind[NCL]={-0.087,0,0.14,0.21,0.24,0.26,0.28,0.31,0.35};
154 static SCALAR CLtable[NCL]={-0.22,0.25,1.02,1.252,1.354,1.44,1.466,1.298,0.97};
156 static SCALAR flap_ind[Ndf]={0,10,20,30};
157 static SCALAR dCLf[Ndf]={0,0.20,0.30,0.35};
158 static SCALAR dCdf[Ndf]={0,0.0021,0.0085,0.0191};
159 static SCALAR dCmf[Ndf]={0,-0.0654,-0.0981,-0.114};
161 static SCALAR flap_transit_rate=2.5;
167 /* printf("Initialize= %d\n",Initialize); */
168 /* printf("Initializing aero model...Initialize= %d\n", Initialize);
170 /*nondimensionalization quantities*/
171 /*units here are ft and lbs */
172 cbar=4.9; /*mean aero chord ft*/
173 b=35.8; /*wing span ft */
174 Sw=174; /*wing planform surface area ft^2*/
175 rPiARe=0.054; /*reciprocal of Pi*AR*e*/
176 lbare=3.682; /*elevator moment arm / MAC*/
185 Cda=0.13; /*Not used*/
194 CLde=-Cmde / lbare; /* kinda backwards, huh? */
216 MaxTakeoffWeight=2550;
224 Cl > 0 => Right wing down
227 elevator > 0 => AND -- aircraft nose down
228 aileron > 0 => right wing up
232 /*do weight & balance here since there is no better place*/
237 else if(Weight < 1500)
243 else if(Dx_cg < -0.4655)
251 if(Flap_handle < flap_ind[0])
253 Flap_handle=flap_ind[0];
254 Flap_Position=flap_ind[0];
256 else if(Flap_handle > flap_ind[3])
258 Flap_handle=flap_ind[3];
259 Flap_Position=flap_ind[3];
265 if((Flap_handle != lastFlapHandle) && (dt > 0))
268 Flap_Position=Flap_handle;
270 lastFlapHandle=Flap_handle;
271 if((Flaps_In_Transit) && (dt > 0))
273 if(Flap_Position < 10)
274 flap_transit_rate = 2.5;
280 if(Flap_Position < Flap_handle)
285 if(fabs(Flap_Position - Flap_handle) > dt*flap_transit_rate)
286 Flap_Position+=flap_dir*flap_transit_rate*dt;
288 if(fabs(Flap_Position - Flap_handle) < dt*flap_transit_rate)
291 Flap_Position=Flap_handle;
298 if(Aft_trim) long_trim = long_trim - trim_inc;
299 if(Fwd_trim) long_trim = long_trim + trim_inc;
301 /* printf("Long_control: %7.4f, long_trim: %7.4f,DEG_TO_RAD: %7.4f, RAD_TO_DEG: %7.4f\n",Long_control,long_trim,DEG_TO_RAD,RAD_TO_DEG);
302 */ /*scale pct control to degrees deflection*/
303 if ((Long_control+long_trim) <= 0)
304 elevator=(Long_control+long_trim)*28*DEG_TO_RAD;
306 elevator=(Long_control+long_trim)*23*DEG_TO_RAD;
308 aileron = -1*Lat_control*17.5*DEG_TO_RAD;
309 rudder = -1*Rudder_pedal*16*DEG_TO_RAD;
311 The aileron travel limits are 20 deg. TEU and 15 deg TED
312 but since we don't distinguish between left and right we'll
313 use the average here (17.5 deg)
317 /*calculate rate derivative nondimensionalization (is that a word?) factors */
318 /*hack to avoid divide by zero*/
319 /*the dynamic terms might be negligible at low ground speeds anyway*/
321 /* printf("Vinf: %g, Span: %g\n",V_rel_wind,b);
323 if(V_rel_wind > DYN_ON_SPEED)
325 cbar_2V=cbar/(2*V_rel_wind);
326 b_2V=b/(2*V_rel_wind);
335 /*calcuate the qS nondimensionalization factors*/
337 qS=Dynamic_pressure*Sw;
342 /* printf("aero: Wb: %7.4f, Ub: %7.4f, Alpha: %7.4f, elev: %7.4f, ail: %7.4f, rud: %7.4f, long_trim: %7.4f\n",W_body,U_body,Alpha*RAD_TO_DEG,elevator*RAD_TO_DEG,aileron*RAD_TO_DEG,rudder*RAD_TO_DEG,long_trim*RAD_TO_DEG);
343 printf("aero: Theta: %7.4f, Gamma: %7.4f, Beta: %7.4f, Phi: %7.4f, Psi: %7.4f\n",Theta*RAD_TO_DEG,Gamma_vert_rad*RAD_TO_DEG,Beta*RAD_TO_DEG,Phi*RAD_TO_DEG,Psi*RAD_TO_DEG);
348 /* sum coefficients */
349 CLwbh = interp(CLtable,alpha_ind,NCL,Alpha);
350 /* printf("CLwbh: %g\n",CLwbh);
352 CLo = CLob + interp(dCLf,flap_ind,Ndf,Flap_Position);
353 Cdo = Cdob + interp(dCdf,flap_ind,Ndf,Flap_Position);
354 Cmo = Cmob + interp(dCmf,flap_ind,Ndf,Flap_Position);
356 /* printf("FP: %g\n",Flap_Position);
357 printf("CLo: %g\n",CLo);
358 printf("Cdo: %g\n",Cdo);
359 printf("Cmo: %g\n",Cmo); */
363 CL = CLo + CLwbh + (CLadot*Alpha_dot + CLq*Theta_dot)*cbar_2V + CLde*elevator;
364 cd = Cdo + rPiARe*CL*CL + Cdde*elevator;
365 cy = Cybeta*Beta + (Cyp*P_body + Cyr*R_body)*b_2V + Cyda*aileron + Cydr*rudder;
367 cm = Cmo + Cma*Alpha + (Cmq*Q_body + Cmadot*Alpha_dot)*cbar_2V + Cmde*(elevator);
368 cn = Cnbeta*Beta + (Cnp*P_body + Cnr*R_body)*b_2V + Cnda*aileron + Cndr*rudder;
369 croll=Clbeta*Beta + (Clp*P_body + Clr*R_body)*b_2V + Clda*aileron + Cldr*rudder;
371 /* printf("aero: CL: %7.4f, Cd: %7.4f, Cm: %7.4f, Cy: %7.4f, Cn: %7.4f, Cl: %7.4f\n",CL,cd,cm,cy,cn,croll);
374 /*calculate wind axes forces*/
379 /* printf("V_rel_wind: %7.4f, Fxwind: %7.4f Fywind: %7.4f Fzwind: %7.4f\n",V_rel_wind,F_X_wind,F_Y_wind,F_Z_wind);
382 /*calculate moments and body axis forces */
386 /* requires ugly wind-axes to body-axes transform */
387 F_X_aero = F_X_wind*Cos_alpha*Cos_beta - F_Y_wind*Cos_alpha*Sin_beta - F_Z_wind*Sin_alpha;
388 F_Y_aero = F_X_wind*Sin_beta + F_Y_wind*Cos_beta;
389 F_Z_aero = F_X_wind*Sin_alpha*Cos_beta - F_Y_wind*Sin_alpha*Sin_beta + F_Z_wind*Cos_alpha;
391 /*no axes transform here */
392 M_l_aero = croll*qSb;
393 M_m_aero = cm*qScbar;
396 /* printf("I_yy: %7.4f, qScbar: %7.4f, qbar: %7.4f, Sw: %7.4f, cbar: %7.4f, 0.5*rho*V^2: %7.4f\n",I_yy,qScbar,Dynamic_pressure,Sw,cbar,0.5*0.0023081*V_rel_wind*V_rel_wind);
398 printf("Fxaero: %7.4f Fyaero: %7.4f Fzaero: %7.4f Weight: %7.4f\n",F_X_aero,F_Y_aero,F_Z_aero,Weight);
400 printf("Maero: %7.4f Naero: %7.4f Raero: %7.4f\n",M_m_aero,M_n_aero,M_l_aero);