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;
152 static SCALAR trim_inc = 0.0002;
154 static SCALAR alpha_ind[NCL]={-0.087,0,0.14,0.21,0.24,0.26,0.28,0.31,0.35};
155 static SCALAR CLtable[NCL]={-0.22,0.25,1.02,1.252,1.354,1.44,1.466,1.298,0.97};
157 static SCALAR flap_ind[Ndf]={0,10,20,30};
158 static SCALAR dCLf[Ndf]={0,0.20,0.30,0.35};
159 static SCALAR dCdf[Ndf]={0,0.0021,0.0085,0.0191};
160 static SCALAR dCmf[Ndf]={0,-0.0654,-0.0981,-0.114};
162 static SCALAR flap_transit_rate=2.5;
168 /* printf("Initialize= %d\n",Initialize); */
169 /* printf("Initializing aero model...Initialize= %d\n", Initialize);
171 /*nondimensionalization quantities*/
172 /*units here are ft and lbs */
173 cbar=4.9; /*mean aero chord ft*/
174 b=35.8; /*wing span ft */
175 Sw=174; /*wing planform surface area ft^2*/
176 rPiARe=0.054; /*reciprocal of Pi*AR*e*/
177 lbare=3.682; /*elevator moment arm / MAC*/
186 Cda=0.13; /*Not used*/
195 CLde=-Cmde / lbare; /* kinda backwards, huh? */
217 MaxTakeoffWeight=2550;
225 Cl > 0 => Right wing down
228 elevator > 0 => AND -- aircraft nose down
229 aileron > 0 => right wing up
233 /*do weight & balance here since there is no better place*/
238 else if(Weight < 1500)
244 else if(Dx_cg < -0.6)
247 Cg=0.25 - Dx_cg/cbar;
253 if(Flap_handle < flap_ind[0])
255 Flap_handle=flap_ind[0];
256 Flap_Position=flap_ind[0];
258 else if(Flap_handle > flap_ind[3])
260 Flap_handle=flap_ind[3];
261 Flap_Position=flap_ind[3];
267 if((Flap_handle != lastFlapHandle) && (dt > 0))
273 Flap_Position=Flap_handle;
275 lastFlapHandle=Flap_handle;
276 if((Flaps_In_Transit) && (dt > 0))
278 if(Flap_Position < 10)
279 flap_transit_rate = 2.5;
285 if(Flap_Position < Flap_handle)
290 if(fabs(Flap_Position - Flap_handle) > dt*flap_transit_rate)
291 Flap_Position+=flap_dir*flap_transit_rate*dt;
293 if(fabs(Flap_Position - Flap_handle) < dt*flap_transit_rate)
296 Flap_Position=Flap_handle;
302 if(Aft_trim) long_trim = long_trim - trim_inc;
303 if(Fwd_trim) long_trim = long_trim + trim_inc;
305 /* 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);
306 */ /*scale pct control to degrees deflection*/
307 if ((Long_control+Long_trim) <= 0)
308 elevator=(Long_control+Long_trim)*28*DEG_TO_RAD;
310 elevator=(Long_control+Long_trim)*23*DEG_TO_RAD;
312 aileron = -1*Lat_control*17.5*DEG_TO_RAD;
313 rudder = -1*Rudder_pedal*16*DEG_TO_RAD;
315 The aileron travel limits are 20 deg. TEU and 15 deg TED
316 but since we don't distinguish between left and right we'll
317 use the average here (17.5 deg)
321 /*calculate rate derivative nondimensionalization (is that a word?) factors */
322 /*hack to avoid divide by zero*/
323 /*the dynamic terms are negligible at low ground speeds anyway*/
325 /* printf("Vinf: %g, Span: %g\n",V_rel_wind,b);
327 if(V_rel_wind > DYN_ON_SPEED)
329 cbar_2V=cbar/(2*V_rel_wind);
330 b_2V=b/(2*V_rel_wind);
339 /*calcuate the qS nondimensionalization factors*/
341 qS=Dynamic_pressure*Sw;
346 /* 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);
347 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);
352 /* sum coefficients */
353 CLwbh = interp(CLtable,alpha_ind,NCL,Alpha);
354 /* printf("CLwbh: %g\n",CLwbh);
356 CLo = CLob + interp(dCLf,flap_ind,Ndf,Flap_Position);
357 Cdo = Cdob + interp(dCdf,flap_ind,Ndf,Flap_Position);
358 Cmo = Cmob + interp(dCmf,flap_ind,Ndf,Flap_Position);
360 /* printf("FP: %g\n",Flap_Position);
361 printf("CLo: %g\n",CLo);
362 printf("Cdo: %g\n",Cdo);
363 printf("Cmo: %g\n",Cmo); */
369 CL = CLo + CLwbh + (CLadot*Alpha_dot + CLq*Theta_dot)*cbar_2V + CLde*elevator;
370 cd = Cdo + rPiARe*Ai*Ai*CL*CL + Cdde*elevator;
371 cy = Cybeta*Beta + (Cyp*P_body + Cyr*R_body)*b_2V + Cyda*aileron + Cydr*rudder;
373 cm = Cmo + Cma*Alpha + (Cmq*Q_body + Cmadot*Alpha_dot)*cbar_2V + Cmde*(elevator);
374 cn = Cnbeta*Beta + (Cnp*P_body + Cnr*R_body)*b_2V + Cnda*aileron + Cndr*rudder;
375 croll=Clbeta*Beta + (Clp*P_body + Clr*R_body)*b_2V + Clda*aileron + Cldr*rudder;
377 /* 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);
380 /*calculate wind axes forces*/
385 /* 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);
388 /*calculate moments and body axis forces */
392 /* requires ugly wind-axes to body-axes transform */
393 F_X_aero = F_X_wind*Cos_alpha*Cos_beta - F_Y_wind*Cos_alpha*Sin_beta - F_Z_wind*Sin_alpha;
394 F_Y_aero = F_X_wind*Sin_beta + F_Y_wind*Cos_beta;
395 F_Z_aero = F_X_wind*Sin_alpha*Cos_beta - F_Y_wind*Sin_alpha*Sin_beta + F_Z_wind*Cos_alpha;
397 /*no axes transform here */
398 M_l_aero = croll*qSb;
399 M_m_aero = cm*qScbar;
402 /* 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);
404 printf("Fxaero: %7.4f Fyaero: %7.4f Fzaero: %7.4f Weight: %7.4f\n",F_X_aero,F_Y_aero,F_Z_aero,Weight);
406 printf("Maero: %7.4f Naero: %7.4f Raero: %7.4f\n",M_m_aero,M_n_aero,M_l_aero);