def avl_section(y, cs, wing, mirror, cs_name, duplicate_sign=1): """create avl wing section.""" b = span(wing['aspect_ratio'], wing['planform'], mirror=mirror) c_r = root_chord(wing['aspect_ratio'], wing['planform'], wing['taper'], mirror=mirror) wing_root_le_pnt = avl.Point(wing['station'], wing['buttline'], wing['waterline']) if mirror: le_point = avl.Point( x=wing_root_le_pnt.x + y * tan(deg2rad(wing['sweep_LE'])), y=y, z=wing_root_le_pnt.z + y * tan(deg2rad(wing['dihedral']))) chord = y_chord(y, c_r, b, wing['taper']) else: le_point = avl.Point(x=wing_root_le_pnt.x + y * tan(deg2rad(wing['sweep_LE'])), y=wing_root_le_pnt.y, z=wing_root_le_pnt.z + y) chord = y_chord(y, c_r, b * 2, wing['taper']) if cs == 0: section = avl.Section(leading_edge_point=le_point, chord=chord, airfoil=avl.NacaAirfoil(wing['airfoil'])) else: control = avl.Control(name=cs_name, gain=1, x_hinge=1 - cs['cf_c'], duplicate_sign=duplicate_sign) section = avl.Section(leading_edge_point=le_point, chord=chord, airfoil=avl.NacaAirfoil(wing['airfoil']), controls=[control]) return section
def i_xz_simple(self): """return empirical aircraft xz axis inertia estimate.""" w = self.aircraft['weight']['weight'] b = span(self.aircraft['wing']['aspect_ratio'], self.aircraft['wing']['planform']) i_xz = ((w / g) * (0.3 * b / 2)**2) / 3 return i_xz
def c_r_beta(self, alpha): """returns rolling moment coefficient wrt sideslip.""" wing = self.plane['wing'] s_w = wing['planform'] # [ft^2] ht = self.plane['horizontal'] s_h = ht['planform'] vt = self.plane['vertical'] s_v = vt['planform'] b = self.b b_h = span(ht['aspect_ratio'], s_h) taper = wing['taper'] taper_h = ht['taper'] z_vt = self.y_mac x_vt = x_mac(z_vt, vt['sweep_LE']) z_v = vt['waterline'] + z_vt - self.plane['weight']['cg'][2] x_v = vt['station'] + x_vt - self.plane['weight']['cg'][0] c_r_b_w_1 = -1 / 6 * self.c_l_alpha_w * (1 + 2 * taper) / ( 1 + taper) * wing['dihedral'] * pi / 180 c_r_b_w_2 = 0.00917 * (wing['waterline'] / (self.plane['fuselage']['height'] / 2) - 1) c_r_b_w_3 = -self.c_l_alpha_w * alpha * (1 + 2 * taper) / ( 1 + taper) * tan(deg2rad(wing['sweep_LE'])) c_r_b_w = c_r_b_w_1 + c_r_b_w_2 + c_r_b_w_3 c_r_b_ht = -1 / 6 * self.c_l_alpha_ht * (1 + 2 * taper_h) / ( 1 + taper_h) * ht['dihedral'] * pi / 180 * s_h * b_h / (s_w * b) c_y_b_vt = -k_yv * abs( self.c_l_alpha_vt) * (self.d_sigma_d_beta_vt * s_v / s_w) c_r_b_vt = c_y_b_vt * (z_v * cos(alpha) - x_v * sin(alpha)) / b c_r_b = c_r_b_w + c_r_b_ht + c_r_b_vt return c_r_b
def propulsion_weight(aircraft): """return engine weight.""" w_p = [] fus = aircraft['fuselage'] w = aircraft['wing'] b = span(w['aspect_ratio'], w['planform']) length = fus['length'] for ii in range(0, aircraft['propulsion']['n_engines']): engine = aircraft['propulsion']["engine_%d" % (ii + 1)] if engine['type'] == 'prop': t = propeller(engine, [0, 0, 0], 0, 1) t = (sum(t[0:3]**2))**0.5 rho = Atmosphere(0).air_density() d = engine['diameter'] a = pi * (d / 2)**2 u_e = (2 * t / (rho * a))**0.5 u_disk = u_e / 2 p = t * u_disk w_controls = 60.27 * ((length + b) * 10**-2)**0.724 w_prop = 32 * (4**0.391) * (d * p * constants.lbft_s2hp() * 10**-3)**0.782 w_prop_control = 4.5 * (4**0.379) * ( d * p * constants.lbft_s2hp() * 10**-3)**0.759 w_engine = p * constants.lbft_s2hp() / constants.electric_hp_lb() w_p.append(w_engine + w_prop + w_prop_control + w_controls) if engine['type'] == 'jet': w_controls = 88.46 * ((length + b) * 10**-2)**0.294 w_engine = engine['thrust'] / constants.jet_lbt_lb() d_nac = 0.04 * engine['thrust']**0.5 l_nac = 0.07 * engine['thrust']**0.5 w_nac = 0.25 * d_nac * l_nac * engine['thrust']**0.36 w_p.append(w_engine + w_controls + w_nac) w_fuel_tank = 1.07 * (aircraft['propulsion']['fuel_mass'] * g)**0.58 w_total = sum(w_p) + w_fuel_tank return w_total
def c_f_m_flap(wing, control, mach, cg): """return flap force and moment coefficient derivatives, empirical method.""" y_scalar = control['b_2'] / abs(control['b_2']) s = wing['planform'] b = span(wing['aspect_ratio'], s) taper = wing['taper'] c_r = root_chord(wing['aspect_ratio'], s, taper) if y_scalar > 0: y_w = b * control['b_2'] / 2 x_w = abs(y_w) * tan(deg2rad(wing['sweep_LE'])) c_r_f = y_chord(abs(control['b_1']) * b / 2, c_r, b, taper) c_t_f = y_chord(abs(control['b_2']) * b / 2, c_r, b, taper) else: y_w = b * control['b_1'] / 2 x_w = abs(y_w) * tan(deg2rad(wing['sweep_LE'])) c_r_f = y_chord(abs(control['b_2']) * b / 2, c_r, b, taper) c_t_f = y_chord(abs(control['b_1']) * b / 2, c_r, b, taper) s_f = flap_area(wing, control) b_f = flap_span(wing, control) ar_f = (b_f**2) / s_f taper_f = c_t_f / c_r_f y_f = y_mac(ar_f, s_f, taper_f) cbar_f = mac(ar_f, s_f, taper_f) ac_f = array( [y_f * tan(deg2rad(wing['sweep_LE'])) + cbar_f / 4, y_f * y_scalar, 0]) ac = (ac_f + array([x_w, y_w, 0]) + array([wing['station'], wing['buttline'], wing['waterline']])) r = (ac - cg) * array([-1, 1, -1]) f = c_f_delta_flap(wing, control, mach) m = cross(r, f) c = concatenate((f, m)) return c
def anti_icing_weight(aircraft): """return cargo/luggage weight.""" w = aircraft['wing'] b = span(w['aspect_ratio'], w['planform']) sweep = w['sweep_LE'] w_ai = b / cos(deg2rad(sweep)) + 3.8 * aircraft['propulsion'][ 'n_engines'] + 1.5 * aircraft['fuselage']['width'] return w_ai
def __init__(self, aircraft, mach): self.plane = aircraft self.mach = mach self.c_l_alpha_w = LiftingSurface(self.plane['wing']).c_l_alpha_wing( mach) # [1/rad] self.c_l_alpha_ht = LiftingSurface( self.plane['horizontal']).c_l_alpha_wing(mach) # [1/rad] self.c_l_alpha_vt = LiftingSurface( self.plane['vertical']).c_l_alpha_wing(mach) # [1/rad] self.s_w = self.plane['wing']['planform'] # [ft^2] self.b = span(self.plane['wing']['aspect_ratio'], self.s_w) self.c_bar = mac(self.plane['wing']['aspect_ratio'], self.s_w, self.plane['wing']['taper']) # [ft] cg = self.plane['weight']['cg'] wing = self.plane['wing'] ht = self.plane['horizontal'] vt = self.plane['vertical'] s_ht = ht['planform'] # [ft^2] s_vt = vt['planform'] # [ft^2] s_w = wing['planform'] # [ft^2] self.y_mac = y_mac(vt['aspect_ratio'], vt['planform'], vt['taper'], mirror=0) self.downwash = LiftingSurface(wing).d_epsilon_d_alpha(ht, mach) self.d_sigma_d_beta_ht = LiftingSurface(wing).d_sigma_d_beta_ht( ht, self.plane['fuselage']) self.d_sigma_d_beta_vt = LiftingSurface(wing).d_sigma_d_beta_vt( vt, self.plane['fuselage']) self.x_ac_ht = LiftingSurface(ht).aerodynamic_center() # [ft] self.x_ac_w = LiftingSurface(wing).aerodynamic_center() # [ft] # elevator cfm_l = c_f_m_flap(ht, ht['control_1'], mach, cg) cfm_r = c_f_m_flap(ht, ht['control_2'], mach, cg) self.cfm_de = (cfm_l + cfm_r) * s_ht / s_w self.cfm_de[3:6] = self.cfm_de[3:6] / array( [self.b, self.c_bar, self.b]) # ailerons cfm_l = c_f_m_flap(wing, wing['control_1'], mach, cg) cfm_r = c_f_m_flap(wing, wing['control_%d' % wing['n_controls']], mach, cg) self.cfm_da = (cfm_l + cfm_r * -1) self.cfm_da[3:6] = self.cfm_da[3:6] / array( [self.b, self.c_bar, self.b]) # rudder cfm_r = c_f_m_flap(vt, vt['control_1'], mach, cg) self.cfm_dr = cfm_r * s_vt / s_w * -1 r = ned_to_body(pi / 2, 0, 0) self.cfm_dr[0:3] = r @ self.cfm_dr[0:3] self.cfm_dr[3:6] = r @ self.cfm_dr[3:6] self.cfm_dr[3:6] = self.cfm_dr[3:6] / array( [self.b, self.c_bar, self.b])
def dihedral(plane, req): y_lg = plane['landing_gear']['main'][1] phi = deg2rad(req['stability_and_control']['lto_roll_angle']) for ii in range(0, plane['propulsion']['n_engines']): b = trapezoidal_wing.span(plane['wing']['aspect_ratio'], plane['wing']['planform']) z_tip = (b / 2 - y_lg) * tan(phi) - plane['wing']['waterline'] gamma = max([rad2deg(arctan(z_tip / (b / 2))), 0]) return gamma
def nonlinear_aero(aircraft, x, u): """return aircraft aero stability axis nonlinear force and moment coefficients.""" altitude = x[-1] # [ft] a = Atmosphere(altitude).speed_of_sound() # [ft/s] v = sqrt(x[0]**2 + x[1]**2 + x[2]**2) # [ft/s] mach = v / a # [] alpha = rad2deg(arctan(x[2] / x[0])) beta = rad2deg(arctan(x[1] / x[0])) model = aircraft['aero_model'] s = aircraft['wing']['planform'] # [ft2] cbar = mac(aircraft['wing']['aspect_ratio'], s, aircraft['wing']['taper']) # [ft] b = span(aircraft['wing']['aspect_ratio'], s) # [ft] p = rad2deg(x[6]) q = rad2deg(x[7]) r = rad2deg(x[8]) d_aileron = rad2deg(u[0]) # [rad] d_elevator = rad2deg(u[1]) # [rad] d_rudder = rad2deg(u[2]) # [rad] names = ['cd', 'cy', 'cl', 'cmr', 'cmp', 'cmy'] c = [] for cfm in names: f_bas = interp2d(model['baseline']['alpha'], model['baseline']['mach'], model['baseline']['cfm'][cfm]) f_lat = interp2d(model['lat_dir']['beta'], model['lat_dir']['mach'], model['lat_dir']['cfm'][cfm]) f_ail = interp2d(model['aileron']['d_aileron'], model['aileron']['mach'], model['aileron']['cfm'][cfm]) f_ele = interp2d(model['elevator']['d_elevator'], model['elevator']['mach'], model['elevator']['cfm'][cfm]) f_rud = interp2d(model['rudder']['d_rudder'], model['rudder']['mach'], model['rudder']['cfm'][cfm]) f_p = interp2d(model['p']['p'], model['p']['mach'], model['p']['cfm'][cfm]) f_q = interp2d(model['q']['q'], model['q']['mach'], model['q']['cfm'][cfm]) f_r = interp2d(model['r']['r'], model['r']['mach'], model['r']['cfm'][cfm]) c.append( float(f_bas(alpha, mach)) + float(f_lat(beta, mach) - f_bas(0, mach)) + float(f_ail(d_aileron, mach) - f_bas(0, mach)) + float(f_ele(d_elevator, mach) - f_bas(0, mach)) + float(f_rud(d_rudder, mach) - f_bas(0, mach)) + float(f_p(p, mach) - f_bas(0, mach)) + float(f_q(q, mach) - f_bas(0, mach)) + float(f_r(r, mach) - f_bas(0, mach))) ac = Aircraft(aircraft, mach) c_aero = (array(c) + array([ac.c_d_zero(altitude), 0, 0, 0, 0, 0])) c_aero_cg = translate_mrc(model['mrc'], aircraft['weight']['cg'], c_aero * array([1, 1, 1, -b, cbar, -b])) c_aero_cg = c_aero_cg * array([1, 1, 1, -1 / b, 1 / cbar, -1 / b]) return c_aero_cg
def i_zz_simple(self): """return empirical aircraft z axis inertia estimate.""" w = self.aircraft['weight']['weight'] b = span(self.aircraft['wing']['aspect_ratio'], self.aircraft['wing']['planform']) d = self.aircraft['fuselage']['length'] e = (b + d) / 2 i = (w / g) * (0.4 * e / 2)**2 return i
def flap_area(wing, control): """return flapped area.""" s = wing['planform'] b = span(wing['aspect_ratio'], s) taper = wing['taper'] c_r = root_chord(wing['aspect_ratio'], s, taper) s_a = ((control['b_2'] - control['b_1']) * b / 4 * (y_chord(abs(control['b_2']) * b / 2, c_r, b, taper) + y_chord(abs(control['b_1']) * b / 2, c_r, b, taper))) return s_a
def trim_aileron(aircraft, v, altitude, p): """trim aircraft with aileron and rudder""" a = Atmosphere(altitude).speed_of_sound() # [ft/s] mach = v / a b = span(aircraft['wing']['aspect_ratio'], aircraft['wing']['planform']) k = b / (2 * v) c_l_p = Aircraft(aircraft, mach).c_r_roll_rate() # [] c_l_da = Aircraft(aircraft, mach).c_r_delta_aileron() # [] da = -c_l_p * p * k / c_l_da da = rad2deg(da) return da
def print_vt(wing): b = span(wing['aspect_ratio'], wing['planform'], mirror=0) c_r = root_chord(wing['aspect_ratio'], wing['planform'], wing['taper']) c_t = c_r * wing['taper'] x = wing['station'] + array([ 0, b / 2 * tan(deg2rad(wing['sweep_LE'])), b / 2 * tan(deg2rad(wing['sweep_LE'])) + c_t, c_r, 0 ]) z = array([0, b, b, 0, 0]) + wing['waterline'] y = array([0, 0, 0, 0, 0]) return x, y, z
def linear_aero(aircraft, x, u): """return aircraft aero stability axis linear force and moment coefficients.""" s = aircraft['wing']['planform'] # [ft2] altitude = x[-1] # [ft] a = Atmosphere(altitude).speed_of_sound() # [ft/s] v = sqrt(x[0]**2 + x[1]**2 + x[2]**2) # [ft/s] mach = v / a # [] alpha = arctan(x[2] / x[0]) # [rad] beta = arctan(x[1] / x[0]) # [rad] c_bar = mac(aircraft['wing']['aspect_ratio'], s, aircraft['wing']['taper']) # [ft] b = span(aircraft['wing']['aspect_ratio'], s) # [ft] p_hat = x[6] * b / (2 * v) # [] q_hat = x[7] * c_bar / (2 * v) # [] r_hat = x[8] * b / (2 * v) # [] d_aileron = u[0] # [rad] d_elevator = u[1] # [rad] d_rudder = u[2] # [rad] alpha_dot = 0 # [] ac = Aircraft(aircraft, mach) cd = (ac.c_d_zero(altitude) + ((ac.c_l_zero() + ac.c_l_alpha() * alpha + ac.c_l_alpha_dot() * alpha_dot + ac.c_l_pitch_rate() * q_hat + ac.c_l_delta_elevator() * d_elevator)**2) / (ac.c_l_alpha() / 2 * aircraft['wing']['aspect_ratio'])) cy = (ac.c_y_beta() * beta + ac.c_y_roll_rate(alpha) * p_hat + ac.c_y_yaw_rate(alpha) * r_hat + ac.c_y_delta_rudder() * d_rudder) cl = (ac.c_l_zero() + ac.c_l_alpha() * alpha + ac.c_l_alpha_dot() * alpha_dot + ac.c_l_pitch_rate() * q_hat + ac.c_l_delta_elevator() * d_elevator) cmr = (ac.c_r_beta(alpha) * beta + ac.c_r_roll_rate() * p_hat + ac.c_r_yaw_rate(alpha) * r_hat + ac.c_r_delta_aileron() * d_aileron + ac.c_r_delta_rudder() * d_rudder) cmp = (ac.c_m_zero(altitude) + ac.c_m_alpha() * alpha + ac.c_m_alpha_dot() * alpha_dot + ac.c_m_pitch_rate() * q_hat + ac.c_m_delta_elevator() * d_elevator) cmy = (ac.c_n_beta(alpha) * beta + ac.c_n_roll_rate(alpha) * p_hat + ac.c_n_yaw_rate(alpha) * r_hat + ac.c_n_delta_aileron() * d_aileron + ac.c_n_delta_rudder() * d_rudder) c_aero = array([cd, cy, cl, cmr, cmp, cmy]) return c_aero
def c_y_yaw_rate(self, alpha): """returns side force coefficient wrt yaw rate.""" wing = self.plane['wing'] s_w = wing['planform'] # [ft^2] vt = self.plane['vertical'] s_v = vt['planform'] z_vt = self.y_mac x_vt = x_mac(z_vt, vt['sweep_LE']) z_v = vt['waterline'] + z_vt - self.plane['weight']['cg'][2] x_v = vt['station'] + x_vt - self.plane['weight']['cg'][0] b = span(wing['aspect_ratio'], s_w) c_y_b_vt = -k_yv * abs( self.c_l_alpha_vt) * (self.d_sigma_d_beta_vt * s_v / s_w) c_y_r = -2 * c_y_b_vt * (x_v * cos(alpha) + z_v * sin(alpha)) / b return c_y_r
def print_wing(wing): b = span(wing['aspect_ratio'], wing['planform']) c_r = root_chord(wing['aspect_ratio'], wing['planform'], wing['taper']) c_t = c_r * wing['taper'] x = wing['station'] + array([ 0, b / 2 * tan(deg2rad(wing['sweep_LE'])), b / 2 * tan(deg2rad(wing['sweep_LE'])) + c_t, c_r, b / 2 * tan(deg2rad(wing['sweep_LE'])) + c_t, b / 2 * tan(deg2rad(wing['sweep_LE'])), 0 ]) y = array([0, b / 2, b / 2, 0, -b / 2, -b / 2, 0]) z = wing['waterline'] + array([ 0, b / 2 * tan(deg2rad(wing['dihedral'])), b / 2 * tan(deg2rad(wing['dihedral'])), 0, b / 2 * tan(deg2rad(wing['dihedral'])), b / 2 * tan(deg2rad(wing['dihedral'])), 0 ]) return x, y, z
def c_m_zero(self, altitude): """baseline lift coefficient.""" wing = self.plane['wing'] s_w = wing['planform'] # [ft^2] ht = self.plane['horizontal'] s_ht = ht['planform'] # [ft^2] vt = self.plane['vertical'] s_vt = vt['planform'] # [ft^2] b_vt = span(vt['aspect_ratio'], s_vt, mirror=0) c_bar = self.c_bar cg_bar = self.plane['weight']['cg'][0] / c_bar # [] z_cg = self.plane['weight']['cg'][2] x_ac_w_bar = self.x_ac_w / c_bar # [] x_ac_ht_bar = self.x_ac_ht / c_bar # [] naca = wing['airfoil'] a_zl = -1.1 * int(naca[0]) naca = ht['airfoil'] a_zl_ht = -1.1 * int(naca[0]) c_l_0_w = self.c_l_alpha_w * ( deg2rad(wing['incidence']) - deg2rad(a_zl)) # [] c_m_0_w = c_l_0_w * (cg_bar - x_ac_w_bar) epsilon = 2 * c_l_0_w / (pi * wing['aspect_ratio']) # [rad] c_l_0_ht = self.c_l_alpha_ht * s_ht / s_w * ( deg2rad(ht['incidence']) - deg2rad(a_zl_ht) - epsilon) # [] z_w = (z_cg - wing['waterline']) / c_bar z_ht = (z_cg - ht['waterline']) / c_bar z_vt = (z_cg - (vt['waterline'] + b_vt / 2)) / c_bar z_f = (z_cg - self.plane['fuselage']['height'] / 2) / c_bar c_m_0_w_d = -LiftingSurface(wing).parasite_drag(self.mach, altitude) * z_w c_m_0_ht_d = -LiftingSurface(ht).parasite_drag( self.mach, altitude) * s_ht / s_w * z_ht c_m_0_vt_d = -LiftingSurface(vt).parasite_drag( self.mach, altitude) * s_vt / s_w * z_vt c_m_0_f_d = -Fuselage(self.plane).parasite_drag_fuselage( self.mach, altitude) * z_f c_m_0_ht = c_l_0_ht * (x_ac_ht_bar - cg_bar) c_m_0 = (c_m_0_w + c_m_0_ht + c_m_0_w_d + c_m_0_ht_d + c_m_0_vt_d + c_m_0_f_d) # [] return c_m_0
def c_f_m(aircraft, x, u, engine_out=False): """return aircraft body axis forces and moments.""" s = aircraft['wing']['planform'] # [ft2] altitude = x[-1] # [ft] a = Atmosphere(altitude).speed_of_sound() # [ft/s] v = sqrt(x[0]**2 + x[1]**2 + x[2]**2) # [ft/s] mach = v / a # [] alpha = arctan(x[2] / x[0]) # [rad] beta = arctan(x[1] / x[0]) # [rad] weight = array([0, 0, 0, 0, 0, 0]) c_bar = mac(aircraft['wing']['aspect_ratio'], s, aircraft['wing']['taper']) # [ft] b = span(aircraft['wing']['aspect_ratio'], s) # [ft] throttle = u[3] * ones(aircraft['propulsion']['n_engines']) # [] if engine_out: throttle[0] = 0.01 # get thrust contributions c_f_m_t = Propulsion(aircraft['propulsion'], x, throttle, aircraft['weight']['cg']).thrust_f_m() # get weight contributions weight[0:3] = aircraft['weight']['weight'] * array( [-sin(x[4]), cos(x[4]) * sin(x[3]), cos(x[4]) * cos(x[3])]) q_bar = dynamic_pressure(mach, altitude) # [psf] s = aircraft['wing']['planform'] # [ft2] if 'aero_model' in aircraft.keys(): c_aero = nonlinear_aero(aircraft, x, u) else: c_aero = linear_aero(aircraft, x, u) c = array([ -c_aero[0], c_aero[1], -c_aero[2], c_aero[3] * b, c_aero[4] * c_bar, c_aero[5] * b ]) * q_bar * s b_2_w = body_to_wind(alpha, beta) c[0:3] = linalg.inv(b_2_w) @ c[0:3] c[3:6] = linalg.inv(b_2_w) @ c[3:6] c = c + c_f_m_t + weight return c
def d_epsilon_d_alpha(self, ht, mach): """return downwash gradient wrt angle of attack, empirical method.""" ar = self.wing['aspect_ratio'] # [] taper = self.wing['taper'] # [] root_chord_wing = root_chord(ar, self.wing['planform'], taper) # [ft] root_chord_ht = root_chord(ht['aspect_ratio'], ht['planform'], ht['taper']) # [ft] x_wh = (ht['station'] + root_chord_ht / 4) - ( self.wing['station'] + root_chord_wing / 4) # [ft] z_wh = ht['waterline'] - self.wing['waterline'] # [ft] b = span(ar, self.wing['planform']) # [ft] r = 2 * x_wh / b # [] m = 2 * z_wh / b # [] k_ar = (1 / ar) - 1 / (1 + ar**1.7) # [] k_taper = (10 - 3 * taper) / 7 # [] k_mr = (1 - (m / 2)) / (r**0.333) # [] sweep_25 = sweep_x(ar, taper, self.wing['sweep_LE'], 0.25) # [deg] beta = sqrt(1 - mach**2) # [] de_da = 4.44 * beta * (k_ar * k_taper * k_mr * sqrt(cos(deg2rad(sweep_25))))**1.19 # [] return de_da
def trim_aileron_rudder(aircraft, v, altitude, alpha, beta, p, r): """trim aircraft with aileron and rudder""" a = Atmosphere(altitude).speed_of_sound() # [ft/s] mach = v / a b = span(aircraft['wing']['aspect_ratio'], aircraft['wing']['planform']) k = b / (2 * v) c_l_b = Aircraft(aircraft, mach).c_r_beta(alpha) c_l_p = Aircraft(aircraft, mach).c_r_roll_rate() # [] c_l_r = Aircraft(aircraft, mach).c_r_yaw_rate(alpha) # [] c_l_da = Aircraft(aircraft, mach).c_r_delta_aileron() # [] c_l_dr = Aircraft(aircraft, mach).c_r_delta_rudder() # [] c_n_b = Aircraft(aircraft, mach).c_n_beta(alpha) # [] c_n_p = Aircraft(aircraft, mach).c_n_roll_rate(alpha) # [] c_n_r = Aircraft(aircraft, mach).c_n_yaw_rate(alpha) # [] c_n_da = Aircraft(aircraft, mach).c_n_delta_aileron() # [] c_n_dr = Aircraft(aircraft, mach).c_n_delta_rudder() # [] a = array([[c_l_da, c_l_dr], [c_n_da, c_n_dr]]) b = array([[-c_l_b * beta - c_l_p * p * k - c_l_r * r * k], [-c_n_b * beta - c_n_p * p * k - c_n_r * r * k]]) c = linalg.solve(a, b) # [rad] return rad2deg(c)
def c_r_roll_rate(self): """returns rolling moment coefficient wrt roll rate.""" wing = self.plane['wing'] s_w = wing['planform'] # [ft^2] ht = self.plane['horizontal'] s_h = ht['planform'] vt = self.plane['vertical'] s_v = vt['planform'] b = self.b b_h = span(ht['aspect_ratio'], s_h) taper = wing['taper'] taper_h = ht['taper'] z_vt = self.y_mac z_v = vt['waterline'] + z_vt - self.plane['weight']['cg'][2] c_r_p_w = -self.c_l_alpha_w * (1 + 3 * taper) / (12 * (1 + taper)) c_r_p_h = -self.c_l_alpha_ht * (1 + 3 * taper_h) / ( 12 * (1 + taper_h)) * s_h / s_w * (b_h / b)**2 c_y_b_vt = -k_yv * abs( self.c_l_alpha_vt) * (self.d_sigma_d_beta_vt * s_v / s_w) c_r_p_v = 2 * c_y_b_vt * (z_v / b)**2 c_r_p = c_r_p_w + c_r_p_h + c_r_p_v return c_r_p
def run_avl(aircraft, mach, alpha, beta, p, q, r, u, iplot=0): """run Athena Vortex Lattice Method.""" case_name = 'zero_alpha' roll_rate = deg2rad(p) # [rad/s] pitch_rate = deg2rad(q) # [rad/s] yaw_rate = deg2rad(r) # [rad/s] d_aileron = u[0] # deg d_elevator = u[1] # deg d_rudder = -u[2] # deg gains = [-1, 1, 1] wing = aircraft['wing'] ht = aircraft['horizontal'] vt = aircraft['vertical'] wing_aspect_ratio = wing['aspect_ratio'] wing_area = wing['planform'] wing_taper = wing['taper'] wing_root_le_pnt = avl.Point(wing['station'], wing['buttline'], wing['waterline']) ht_aspect_ratio = ht['aspect_ratio'] ht_area = ht['planform'] ht_root_le_pnt = avl.Point(ht['station'], ht['buttline'], ht['waterline']) vt_aspect_ratio = vt['aspect_ratio'] vt_area = vt['planform'] vt_root_le_pnt = avl.Point(vt['station'], vt['buttline'], vt['waterline']) a = Atmosphere(0).speed_of_sound() ref_pnt = avl.Point(aircraft['weight']['cg'][0], aircraft['weight']['cg'][1], aircraft['weight']['cg'][2]) # Wing ------------------------------------------------------------------------------------------------------------- wing_span = span(wing_aspect_ratio, wing_area) wing_mac = mac(wing_aspect_ratio, wing_area, wing_taper) sections = list() if not wing['control_1']['b_2'] == 0: sections.append(avl_section(wing_root_le_pnt[1], 0, wing, 1, [])) sections.append( avl_section(wing_root_le_pnt[1] + wing_span * 0.5 * -wing['control_1']['b_2'], wing['control_1'], wing, 1, 'aileron', duplicate_sign=-1)) sections.append( avl_section(wing_root_le_pnt[1] + wing_span * 0.5 * -wing['control_1']['b_1'], wing['control_1'], wing, 1, 'aileron', duplicate_sign=-1)) if not wing['control_1']['b_1'] == -1: sections.append( avl_section(wing_root_le_pnt[1] + wing_span * 0.5, 0, wing, 1, [])) # y_duplicate=0.0 duplicates the wing over a XZ-plane at Y=0.0 wing = avl.Surface(name='wing', n_chordwise=12, chord_spacing=avl.Spacing.cosine, n_spanwise=20, span_spacing=avl.Spacing.cosine, y_duplicate=0.0, sections=sections) # HT --------------------------------------------------------------------------------------------------------------- ht_span = span(ht_aspect_ratio, ht_area) sections = list() if not ht['control_2']['b_1'] == 0: sections.append(avl_section(ht_root_le_pnt[1], 0, ht, 1, [])) sections.append( avl_section(ht_root_le_pnt[1] + ht_span * 0.5 * ht['control_2']['b_1'], ht['control_2'], ht, 1, 'elevator')) sections.append( avl_section(ht_root_le_pnt[1] + ht_span * 0.5 * ht['control_2']['b_2'], ht['control_2'], ht, 1, 'elevator')) if not ht['control_2']['b_2'] == 1: sections.append( avl_section(ht_root_le_pnt[1] + ht_span * 0.5, 0, ht, 1, [])) horizontal_tail = avl.Surface(name='horizontal_tail', n_chordwise=12, chord_spacing=avl.Spacing.cosine, n_spanwise=20, span_spacing=avl.Spacing.cosine, y_duplicate=0.0, sections=sections) # VT --------------------------------------------------------------------------------------------------------------- vt_span = span(vt_aspect_ratio, vt_area, mirror=0) sections = list() if not vt['control_1']['b_1'] == 0: sections.append(avl_section(vt_root_le_pnt[1], 0, vt, 0, [])) sections.append( avl_section(vt_root_le_pnt[1] + vt_span * vt['control_1']['b_1'], vt['control_1'], vt, 0, 'rudder')) sections.append( avl_section(vt_root_le_pnt[1] + vt_span * vt['control_1']['b_2'], vt['control_1'], vt, 0, 'rudder')) if not vt['control_1']['b_2'] == 1: sections.append(avl_section(vt_root_le_pnt[1] + vt_span, 0, vt, 0, [])) vertical_tail = avl.Surface(name='vertical_tail', n_chordwise=12, chord_spacing=avl.Spacing.cosine, n_spanwise=20, span_spacing=avl.Spacing.cosine, sections=sections) # Setup ------------------------------------------------------------------------------------------------------------ aircraft = avl.Geometry(name='aircraft', reference_area=wing_area, reference_chord=wing_mac, reference_span=wing_span, reference_point=ref_pnt, mach=mach, surfaces=[wing, horizontal_tail, vertical_tail]) def show_treffz(session_1): if 'gs_bin' in session_1.config.settings: images = session_1.save_trefftz_plots() for iimg in images: avl.show_image(iimg) else: for idx, _ in enumerate(session_1.cases): session_1.show_trefftz_plot(idx + 1) # cases start from 1 simple_case = avl.Case(name=case_name, alpha=alpha, beta=beta, aileron=gains[0] * d_aileron, elevator=gains[1] * d_elevator, rudder=gains[2] * d_rudder, roll_rate=roll_rate * wing_span / (2 * mach * a), pitch_rate=pitch_rate * wing_mac / (2 * mach * a), yaw_rate=yaw_rate * wing_span / (2 * mach * a)) session = avl.Session(geometry=aircraft, cases=[simple_case]) if iplot: if 'gs_bin' in session.config.settings: img = session.save_geometry_plot()[0] avl.show_image(img) else: session.show_geometry() show_treffz(session) # results are in a dictionary result = session.run_all_cases() cd = result[case_name]['Totals']['CXtot'] cy = result[case_name]['Totals']['CYtot'] cl = result[case_name]['Totals']['CLtot'] cmr = result[case_name]['Totals']['Cltot'] cmp = result[case_name]['Totals']['Cmtot'] cmy = result[case_name]['Totals']['Cntot'] print("cfm= {}".format([cd, cy, cl, cmr, cmp, cmy])) return [cd, cy, cl, cmr, cmp, cmy]
from src.modeling.trapezoidal_wing import mac, root_chord, span, sweep_x, x_mac, y_chord, y_mac from test.test_library import is_close ar = 5 s = 10 sweep_le = 30 taper = 0.5 c_bar = mac(ar, s, taper) cr = root_chord(ar, s, taper) b = span(ar, s) sweep = sweep_x(ar, taper, sweep_le, 0.5) y = y_mac(ar, s, taper) x = x_mac(3, sweep_le) c = y_chord(0.25, cr, b, taper) out = list() out.append((is_close(c_bar, 1.46659))) out.append(is_close(b, 7.071067)) out.append(is_close(cr, 1.8856)) out.append(is_close(c, 1.81895)) out.append(is_close(x, 1.73205)) out.append(is_close(y, 1.5713)) out.append(is_close(sweep, 23.942)) if any(out): print("trapezoidal wing test passed!") else: print("trapezoidal wing test failed")
def design(plane, requirements, wing_height='high', tail='conventional', engine='wing_mounted', landing_gear='fuselage', propulsion='h2'): if propulsion == 'h2': plane['propulsion']['energy_density'] = constants.energy_density_h2( ) * 2655224 / 0.0685218 plane['propulsion']['total_efficiency'] = constants.eta_electric() elif propulsion == 'battery': plane['propulsion']['energy_density'] = constants.energy_density_li_s( ) * 2655224 / 0.0685218 plane['propulsion']['total_efficiency'] = constants.eta_electric() elif propulsion == 'turboprop': plane['propulsion']['energy_density'] = constants.energy_density_jet_a( ) * 2655224 / 0.0685218 plane['propulsion']['total_efficiency'] = constants.eta_turboprop() l_cab = Fuselage(plane).far_25_length() plane['fuselage']['length'] = plane['fuselage']['length'] - plane[ 'fuselage']['l_cabin'] + l_cab plane['fuselage']['l_cabin'] = l_cab a, b, dy, w = Fuselage(plane).cross_section() plane['fuselage']['height'] = 2 * a plane['fuselage']['width'] = 2 * b plane['weight']['weight'], cg = MassProperties(plane).weight_buildup( requirements) plane['horizontal']['station'] = plane['fuselage']['length'] - 3 plane['vertical']['station'] = plane['fuselage']['length'] - 5 plane['horizontal']['waterline'] = plane['fuselage']['height'] - 2 plane['vertical']['waterline'] = plane['fuselage']['height'] - 2 if wing_height == 'low': plane['wing']['waterline'] = 0 else: plane['wing']['waterline'] = plane['fuselage']['height'] if tail == 'T': plane['vertical']['taper'] = 0.7 v_cruise = (requirements['performance']['cruise_mach'] * Atmosphere( requirements['performance']['cruise_altitude']).speed_of_sound()) v_stall = requirements['performance']['stall_speed'] dw = 100 # iterative while abs(dw) > 10: print('dw = %d' % dw) w_i = plane['weight']['weight'] plane['weight']['weight'], cg = MassProperties(plane).weight_buildup( requirements) i_xx = MassProperties(plane).i_xx_simple() i_yy = MassProperties(plane).i_yy_simple() i_zz = MassProperties(plane).i_zz_simple() i_xz = MassProperties(plane).i_xz_simple() w_s, t_w = wing_loading(plane, requirements) plane['weight']['inertia'] = [[i_xx, 0, i_xz], [0, i_yy, 0], [i_xz, 0, i_zz]] plane['wing']['planform'] = plane['weight']['weight'] / w_s t = plane['weight']['weight'] * t_w thrust = array([ t * Atmosphere(0).air_density() / 0.00238, t * Atmosphere( requirements['performance']['cruise_altitude']).air_density() / 0.00238, t * Atmosphere( requirements['performance']['cruise_altitude']).air_density() / 0.00238 ]) out_prop = propulsion_sizing( plane, thrust, array([v_stall, v_cruise - 200, v_cruise]), array([ 0, requirements['performance']['cruise_altitude'], requirements['performance']['cruise_altitude'] ]), tol=10e-4) for ii in range(0, plane['propulsion']['n_engines']): plane['propulsion']["engine_%d" % (ii + 1)]['pitch'] = out_prop[0] plane['propulsion']["engine_%d" % (ii + 1)]['diameter'] = out_prop[1] plane['propulsion']["engine_%d" % (ii + 1)]['rpm_max'] = out_prop[2] * 1000 plane['wing']['station'], plane['weight']['cg'] = wing_location( plane, requirements, 300, 20000) if tail == 'T': plane['horizontal']['waterline'] = plane['vertical'][ 'waterline'] + trapezoidal_wing.span( plane['vertical']['aspect_ratio'], plane['vertical']['planform'], mirror=0) elif tail == 'conventional': plane['horizontal']['waterline'] = plane['vertical']['waterline'] engine_height(plane, requirements) plane['wing']['dihedral'] = dihedral(plane, requirements) if engine == 'wing_mounted': for ii in range(0, plane['propulsion']['n_engines']): plane['propulsion']["engine_%d" % (ii + 1)]['station'] = plane['wing']['station'] elif engine == 'fuselage_mounted': for ii in range(0, plane['propulsion']['n_engines']): plane['propulsion']["engine_%d" % ( ii + 1)]['station'] = l_cab + plane['fuselage']['l_cockpit'] + 5 x_ng, x_mg, y_mg, l_g = landing_gear_location(plane, mount=landing_gear) plane['landing_gear']['nose'] = [x_ng, 0, -l_g] plane['landing_gear']['main'] = [x_mg, y_mg, -l_g] plane['horizontal']['station'] = min([ x_mg + (plane['horizontal']['waterline'] + l_g) / tan(deg2rad(plane['wing']['alpha_stall'] + 2)), plane['fuselage']['length'] - 3 ]) plane['vertical']['station'] = plane['horizontal']['station'] - 2 c = trim_alpha_de_nonlinear( plane, v_cruise, requirements['performance']['cruise_altitude'], 0) u = array([0, deg2rad(c[0]), 0, 1]) x = array([ float(v_cruise * cos(deg2rad(c[1]))), 0, float(v_cruise * sin(deg2rad(c[1]))), 0, float(deg2rad(c[1])), 0, 0, 0, 0, 0, 0, requirements['performance']['cruise_altitude'] ]) out = longitudinal_sizing(plane, requirements, x, u) plane['wing']['station'] = out[0] plane['horizontal']['planform'] = out[1] plane['vertical']['planform'] = vertical_tail(plane, requirements, x, u) plane['propulsion']['fuel_mass'] = range_iter(plane, requirements) / g plane['weight']['weight'], cg = MassProperties(plane).weight_buildup( requirements) dw = w_i - plane['weight']['weight'] plane['horizontal']['control_1']['cf_c'] = elevator(plane, requirements) plane['vertical']['control_1']['cf_c'] = rudder(plane, requirements) print_plane(plane) return plane
def flap_span(wing, control): """return flap span.""" b = span(wing['aspect_ratio'], wing['planform']) b_f = (control['b_2'] - control['b_1']) * b / 2 return b_f