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_;
119 SCALAR Cda; /*Not used*/
146 /*nondimensionalization quantities*/
147 /*units here are ft and lbs */
148 SCALAR cbar; /*mean aero chord ft*/
149 SCALAR b; /*wing span ft */
150 SCALAR Sw; /*wing planform surface area ft^2*/
151 SCALAR rPiARe; /*reciprocal of Pi*AR*e*/
152 SCALAR lbare; /*elevator moment arm MAC*/
154 SCALAR Weight; /*lbs*/
155 SCALAR MaxTakeoffWeight,EmptyWeight;
160 SCALAR CLwbh,CL,cm,cd,cn,cy,croll,cbar_2V,b_2V,qS,qScbar,qSb;
163 SCALAR F_X_wind,F_Y_wind,F_Z_wind;
168 SCALAR elevator, aileron, rudder;
171 SCALAR Flap_Position;
173 int Flaps_In_Transit;
175 static SCALAR interp(SCALAR *y_table, SCALAR *x_table, int Ntable, SCALAR x)
182 /* if x is outside the table, return value at x[0] or x[Ntable-1]*/
186 /* printf("x smaller than x_table[0]: %g %g\n",x,x_table[0]); */
188 else if(x >= x_table[Ntable-1])
190 slope=(y_table[Ntable-1]-y_table[Ntable-2])/(x_table[Ntable-1]-x_table[Ntable-2]);
191 y=slope*(x-x_table[Ntable-1]) +y_table[Ntable-1];
193 /* printf("x larger than x_table[N]: %g %g %d\n",x,x_table[NCL-1],Ntable-1);
195 else /*x is within the table, interpolate linearly to find y value*/
198 while(x_table[i] <= x) {i++;}
199 slope=(y_table[i]-y_table[i-1])/(x_table[i]-x_table[i-1]);
200 /* 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); */
201 y=slope*(x-x_table[i-1]) +y_table[i-1];
207 void c172_aero( SCALAR dt, int Initialize ) {
212 static SCALAR lastFlapHandle=0;
215 static SCALAR trim_inc = 0.0002;
217 static SCALAR alpha_ind[NCL]={-0.087,0,0.14,0.21,0.24,0.26,0.28,0.31,0.35};
218 static SCALAR CLtable[NCL]={-0.22,0.25,1.02,1.252,1.354,1.44,1.466,1.298,0.97};
220 static SCALAR flap_ind[Ndf]={0,10,20,30};
221 static SCALAR flap_times[Ndf]={0,4,2,2};
222 static SCALAR dCLf[Ndf]={0,0.20,0.30,0.35};
223 static SCALAR dCdf[Ndf]={0,0.0021,0.0085,0.0191};
224 static SCALAR dCmf[Ndf]={0,-0.0654,-0.0981,-0.114};
226 static SCALAR flap_transit_rate=2.5;
232 /* printf("Initialize= %d\n",Initialize); */
233 /* printf("Initializing aero model...Initialize= %d\n", Initialize);
235 /*nondimensionalization quantities*/
236 /*units here are ft and lbs */
237 cbar=4.9; /*mean aero chord ft*/
238 b=35.8; /*wing span ft */
239 Sw=174; /*wing planform surface area ft^2*/
240 rPiARe=0.054; /*reciprocal of Pi*AR*e*/
241 lbare=3.682; /*elevator moment arm / MAC*/
250 Cda=0.13; /*Not used*/
259 CLde=-Cmde / lbare; /* kinda backwards, huh? */
281 MaxTakeoffWeight=2550;
289 Cl > 0 => Right wing down
292 elevator > 0 => AND -- aircraft nose down
293 aileron > 0 => right wing up
297 /*do weight & balance here since there is no better place*/
302 else if(Weight < 1500)
308 else if(Dx_cg < -0.6)
311 Cg=0.25 - Dx_cg/cbar;
317 if(Flap_handle < flap_ind[0])
320 Flap_handle=flap_ind[0];
321 lastFlapHandle=Flap_handle;
322 Flap_Position=flap_ind[0];
324 else if(Flap_handle > flap_ind[Ndf-1])
327 Flap_handle=flap_ind[fi];
328 lastFlapHandle=Flap_handle;
329 Flap_Position=flap_ind[fi];
335 Flap_Position=Flap_handle;
338 if(Flap_handle != lastFlapHandle)
345 while(flap_ind[fi] < Flap_handle) { fi++; }
346 if(Flap_Position < Flap_handle)
348 if(flap_times[fi] > 0)
349 flap_transit_rate=(flap_ind[fi] - flap_ind[fi-1])/flap_times[fi];
351 flap_transit_rate=(flap_ind[fi] - flap_ind[fi-1])/5;
355 if(flap_times[fi+1] > 0)
356 flap_transit_rate=(flap_ind[fi] - flap_ind[fi+1])/flap_times[fi+1];
358 flap_transit_rate=(flap_ind[fi] - flap_ind[fi+1])/5;
360 if(fabs(Flap_Position - Flap_handle) > dt*flap_transit_rate)
361 Flap_Position+=flap_transit_rate*dt;
365 Flap_Position=Flap_handle;
369 lastFlapHandle=Flap_handle;
372 if(Aft_trim) long_trim = long_trim - trim_inc;
373 if(Fwd_trim) long_trim = long_trim + trim_inc;
375 /* 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);
376 */ /*scale pct control to degrees deflection*/
377 if ((Long_control+Long_trim) <= 0)
378 elevator=(Long_control+Long_trim)*28*DEG_TO_RAD;
380 elevator=(Long_control+Long_trim)*23*DEG_TO_RAD;
382 aileron = -1*Lat_control*17.5*DEG_TO_RAD;
383 rudder = -1*Rudder_pedal*16*DEG_TO_RAD;
385 The aileron travel limits are 20 deg. TEU and 15 deg TED
386 but since we don't distinguish between left and right we'll
387 use the average here (17.5 deg)
391 /*calculate rate derivative nondimensionalization (is that a word?) factors */
392 /*hack to avoid divide by zero*/
393 /*the dynamic terms are negligible at low ground speeds anyway*/
395 /* printf("Vinf: %g, Span: %g\n",V_rel_wind,b);
397 if(V_rel_wind > DYN_ON_SPEED)
399 cbar_2V=cbar/(2*V_rel_wind);
400 b_2V=b/(2*V_rel_wind);
409 /*calcuate the qS nondimensionalization factors*/
411 qS=Dynamic_pressure*Sw;
416 /* 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);
417 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);
422 /* sum coefficients */
423 CLwbh = interp(CLtable,alpha_ind,NCL,Std_Alpha);
424 /* printf("CLwbh: %g\n",CLwbh);
426 CLo = CLob + interp(dCLf,flap_ind,Ndf,Flap_Position);
427 Cdo = Cdob + interp(dCdf,flap_ind,Ndf,Flap_Position);
428 Cmo = Cmob + interp(dCmf,flap_ind,Ndf,Flap_Position);
430 /* printf("FP: %g\n",Flap_Position);
431 printf("CLo: %g\n",CLo);
432 printf("Cdo: %g\n",Cdo);
433 printf("Cmo: %g\n",Cmo); */
439 CL = CLo + CLwbh + (CLadot*Std_Alpha_dot + CLq*Theta_dot)*cbar_2V + CLde*elevator;
440 cd = Cdo + rPiARe*Ai*Ai*CL*CL + Cdde*elevator;
441 cy = Cybeta*Std_Beta + (Cyp*P_body + Cyr*R_body)*b_2V + Cyda*aileron + Cydr*rudder;
443 cm = Cmo + Cma*Std_Alpha + (Cmq*Q_body + Cmadot*Std_Alpha_dot)*cbar_2V + Cmde*(elevator);
444 cn = Cnbeta*Std_Beta + (Cnp*P_body + Cnr*R_body)*b_2V + Cnda*aileron + Cndr*rudder;
445 croll=Clbeta*Std_Beta + (Clp*P_body + Clr*R_body)*b_2V + Clda*aileron + Cldr*rudder;
447 /* 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);
450 /*calculate wind axes forces*/
455 /* 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);
458 /*calculate moments and body axis forces */
462 /* requires ugly wind-axes to body-axes transform */
463 F_X_aero = F_X_wind*Cos_alpha*Cos_beta - F_Y_wind*Cos_alpha*Sin_beta - F_Z_wind*Sin_alpha;
464 F_Y_aero = F_X_wind*Sin_beta + F_Y_wind*Cos_beta;
465 F_Z_aero = F_X_wind*Sin_alpha*Cos_beta - F_Y_wind*Sin_alpha*Sin_beta + F_Z_wind*Cos_alpha;
467 /*no axes transform here */
468 M_l_aero = croll*qSb;
469 M_m_aero = cm*qScbar;
472 /* 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);
474 printf("Fxaero: %7.4f Fyaero: %7.4f Fzaero: %7.4f Weight: %7.4f\n",F_X_aero,F_Y_aero,F_Z_aero,Weight);
476 printf("Maero: %7.4f Naero: %7.4f Raero: %7.4f\n",M_m_aero,M_n_aero,M_l_aero);