def WOT_speed(altitude, weight = 2100, rpm = 2700, temp = 'std', \ temp_units = 'C', rv = 'F1', wing_area = 102, speed_units = 'kt', \ prop_eff = 0.78, MP_loss = 1.322, ram = 0.5, rated_power=275): """ Returns the predicted speed at full throttle. The MP_loss is the MP lost in the induction tract at full throttle at 2700 rpm at MSL. The default value is from the Lycoming power charts. The ram is the percentage of available ram recovery pressure that is achieved in the MP. """ press = SA.alt2press(altitude, press_units='in HG') MP_loss = MP_loss * (rpm / 2700.)**2 cas_guess = 300 error = 1 while error > 0.0001: dp = A.cas2dp(cas_guess, press_units='in HG') # print 'dp =', dp ram_press = ram * dp # print 'Ram rise =', ram_press MP = press - MP_loss + ram_press pwr = O.pwr(rpm, MP, altitude, temp=temp, temp_units=temp_units) * rated_power / 180 print('MP =', MP, 'Power =', pwr) tas = speed(altitude, weight, pwr, rpm, temp = temp, \ temp_units = temp_units, rv = rv, wing_area = wing_area, \ speed_units = speed_units, prop_eff = prop_eff) cas = A.tas2cas(tas, altitude, temp=temp, temp_units=temp_units) error = M.fabs((cas - cas_guess) / cas) cas_guess = cas # print 'CAS =', cas, 'TAS =', tas return tas
def WOT_speed(altitude, weight = 2100, rpm = 2700, temp = 'std', \ temp_units = 'C', rv = 'F1', wing_area = 102, speed_units = 'kt', \ prop_eff = 0.78, MP_loss = 1.322, ram = 0.5, rated_power=275): """ Returns the predicted speed at full throttle. The MP_loss is the MP lost in the induction tract at full throttle at 2700 rpm at MSL. The default value is from the Lycoming power charts. The ram is the percentage of available ram recovery pressure that is achieved in the MP. """ press = SA.alt2press(altitude, press_units = 'in HG') MP_loss = MP_loss * (rpm / 2700.) ** 2 cas_guess = 300 error = 1 while error > 0.0001: dp = A.cas2dp(cas_guess, press_units = 'in HG') # print 'dp =', dp ram_press = ram * dp # print 'Ram rise =', ram_press MP = press - MP_loss + ram_press pwr = O.pwr(rpm, MP, altitude, temp = temp, temp_units = temp_units) * rated_power/180 print 'MP =', MP, 'Power =', pwr tas = speed(altitude, weight, pwr, rpm, temp = temp, \ temp_units = temp_units, rv = rv, wing_area = wing_area, \ speed_units = speed_units, prop_eff = prop_eff) cas = A.tas2cas(tas, altitude, temp = temp, temp_units = temp_units) error = M.fabs((cas - cas_guess) / cas) cas_guess = cas # print 'CAS =', cas, 'TAS =', tas return tas
def roca(altitude, weight=2100, press_drop=1.2, temp='std', temp_units='C', prop_eff=0.7, load_factor=1, rated_power=275, rpm=2700): """ Returns speed for best rate of climb and the rate of climb at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = O.pwr(rpm, MP, altitude, temp=temp, temp_units=temp_units) * rated_power / 180 roc_max = -100000 eass = range(60, 150, 1) rocs = [] for eas in eass: rocs.append((roc(altitude, eas, weight, pwr, 2700, temp=temp, prop_eff=prop_eff, load_factor=load_factor), eas)) mroc, meas = max(rocs) return meas, mroc
def aoca(prop, altitude, weight = 1800, press_drop = 1.2, temp = 'std', \ climb = True): """ Returns speed for best climb or descent gradient and the gradient at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = IO.pwr(2700, MP, altitude, temp=temp) if climb == True: eass = list(range(550, 800, 1)) else: eass = list(range(700, 1200, 1)) aocs = [] if climb == True: for eas in eass: aocs.append((aoc(prop, altitude, eas / 10., weight, pwr, 2700, temp=temp), eas)) else: for eas in eass: aocs.append((aoc(prop, altitude, eas / 10., weight, 0, 2700, temp=temp), eas)) maoc, meas = max(aocs) return meas / 10., maoc
def test_01(self): # Truth values from NASA RP 1046 Value = SA.alt2press(5000) Truth = 24.8959 self.failUnless(RE(Value, Truth) <= 1e-5)
def test_01(self): # Truth values from NASA RP 1046 Value = SA.alt2press(5000) Truth = 24.8959 self.assertTrue(RE(Value, Truth) <= 1e-5)
def test_03(self): # test pa and m # Truth values from NASA RP 1046 Value = SA.alt2press(25000, alt_units='m', press_units='pa') Truth = 2511.01 self.assertTrue(RE(Value, Truth) <= 1e-5)
def test_06(self): # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(65322, press_units='pa', alt_units='m') Truth = 9.4609 self.assertTrue(RE(Value, Truth) <= 5e-5)
def test_02(self): # test psf # Truth values from NASA RP 1046 Value = SA.alt2press(49000, press_units='psf') Truth = 254.139 self.assertTrue(RE(Value, Truth) <= 1e-5)
def test_03(self): # test pa and m # Truth values from NASA RP 1046 Value = SA.alt2press(25000, alt_units='m', press_units='pa') Truth = 2511.01 self.failUnless(RE(Value, Truth) <= 1e-5)
def test_06(self): # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(65322, press_units='pa', alt_units='m') Truth = 9.4609 self.failUnless(RE(Value, Truth) <= 5e-5)
def test_02(self): # test psf # Truth values from NASA RP 1046 Value = SA.alt2press(49000, press_units='psf') Truth = 254.139 self.failUnless(RE(Value, Truth) <= 1e-5)
def test_05(self): # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(49610, press_units='pa', alt_units='m') Truth = 79.779 self.failUnless(RE(Value, Truth) <= 3e-5)
def test_05(self): # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(49610, press_units="pa", alt_units="m") Truth = 79.779 self.failUnless(RE(Value, Truth) <= 3e-5)
def test_07(self): # test units in other order # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(80956, press_units='pa', alt_units='m') Truth = 0.75009 self.assertTrue(RE(Value, Truth) <= 1e-4)
def test_07(self): # test units in other order # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(80956, press_units='pa', alt_units='m') Truth = 0.75009 self.failUnless(RE(Value, Truth) <= 1e-4)
def test_04(self): # test units in other order # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(39750, press_units='pa', alt_units='m') Truth = 287.14 self.failUnless(RE(Value, Truth) <= 1e-5)
def test_04(self): # test units in other order # truth value calculated from program at: # http://www.sworld.com.au/steven/space/atmosphere/ Value = SA.alt2press(39750, press_units="pa", alt_units="m") Truth = 287.14 self.failUnless(RE(Value, Truth) <= 1e-5)
def MP_pred(tas, alt, rpm, rpm_base = 2700., MP_loss = 1.322, ram = 0.5, temp='std'): press = SA.alt2press(alt, press_units = 'in HG') if temp == 'std': temp = SA.alt2temp(alt) dp = A.tas2dp(tas, alt, temp, speed_units='kt', alt_units='ft', temp_units='C', press_units='in HG') ram_press = ram * dp MP_loss = MP_loss * (rpm / rpm_base) ** 1.85 # exponent from various online pressure drop calculators # MP_loss = MP_loss * (rpm / rpm_base) MP = press - MP_loss + ram_press # print "MP = %.3f" % MP return MP
def alt2pwr(alt, rpm = 2700, MP_max = 30, temp = 'std', alt_units = 'ft', \ temp_units = 'C'): """ Returns power at a given altitude. Default rpm is 2700. The maximum MP may be specified, if for example, one wanted to use 25 inches MP until full throttle was reached. """ # MP loss at full throttle at 2700 rpm at sea level. # From Lycoming power chart MP_loss_base = 29.9213 - 28.6 press = SA.alt2press(alt, alt_units = alt_units) # assume pressure drop is proportional to square of velocity MP_loss = MP_loss_base * (rpm / 2700.) ** 2 MP = min(press - MP_loss, MP_max) # from climb testing, get MP of 0.5 above ambient # get 2650 rpm during climb MP = SA.alt2press(alt) + 0.5 * (2650./rpm) ** 2 pwr = IO.pwr(rpm, MP, alt, temp = temp, alt_units = alt_units, \ temp_units = temp_units) # decrement power as a function of altitude to make predicted climb perf match flight test resutls # this decrement is optimized for the MT prop pwr = pwr * (0.8525 - 4.35E-10 * alt**2) return pwr
def alt2pwr(alt, rpm = 2700, MP_max = 30, temp = 'std', alt_units = 'ft', \ temp_units = 'C'): """ Returns power at a given altitude. Default rpm is 2700. The maximum MP may be specified, if for example, one wanted to use 25 inches MP until full throttle was reached. """ # MP loss at full throttle at 2700 rpm at sea level. # From Lycoming power chart MP_loss_base = 29.9213 - 28.6 press = SA.alt2press(alt, alt_units=alt_units) # assume pressure drop is proportional to square of velocity MP_loss = MP_loss_base * (rpm / 2700.)**2 MP = min(press - MP_loss, MP_max) # from climb testing, get MP of 0.5 above ambient # get 2650 rpm during climb MP = SA.alt2press(alt) + 0.5 * (2650. / rpm)**2 pwr = IO.pwr(rpm, MP, alt, temp = temp, alt_units = alt_units, \ temp_units = temp_units) # decrement power as a function of altitude to make predicted climb perf match flight test resutls # this decrement is optimized for the MT prop pwr = pwr * (0.8525 - 4.35E-10 * alt**2) return pwr
def roca(prop, altitude, weight = 1800, press_drop = 1.2, temp = 'std', \ load_factor =1, prop_factor=1): """ Returns speed for best rate of climb and the rate of climb at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = IO.pwr(2700, MP, altitude, temp=temp) roc_max = -100000 eass = list(range(600, 1500, 1)) rocs = [] for eas in eass: rocs.append((roc(prop, altitude, eas/10., weight, pwr, 2700, temp = temp, \ load_factor = load_factor, prop_factor=prop_factor),eas/10.)) mroc, meas = max(rocs) return meas, mroc
def roca(prop, altitude, weight = 1800, press_drop = 1.2, temp = 'std', \ load_factor =1, prop_factor=1): """ Returns speed for best rate of climb and the rate of climb at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = IO.pwr(2700, MP, altitude, temp = temp) roc_max = -100000 eass = range(600, 1500, 1) rocs = [] for eas in eass: rocs.append((roc(prop, altitude, eas/10., weight, pwr, 2700, temp = temp, \ load_factor = load_factor, prop_factor=prop_factor),eas/10.)) mroc, meas = max(rocs) return meas, mroc
def roca(altitude, weight = 2100, press_drop = 1.2, temp = 'std', \ temp_units='C', prop_eff = 0.7, load_factor =1, rated_power=275, \ rpm=2700): """ Returns speed for best rate of climb and the rate of climb at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = O.pwr(rpm, MP, altitude, temp = temp, temp_units = temp_units) * rated_power/180 roc_max = -100000 eass = range(60, 150, 1) rocs = [] for eas in eass: rocs.append((roc(altitude, eas, weight, pwr, 2700, temp = temp, \ prop_eff = prop_eff, load_factor = load_factor),eas)) mroc, meas = max(rocs) return meas, mroc
def WOT_speed_orig(prop, altitude, weight = 1800, rpm = 2700, temp = 'std', \ temp_units = 'C', rv = '8', wing_area = 110, speed_units = 'kt' , \ MP_loss = 1.322, ram = 0.5, pwr_factor=1, mixture='pwr', \ wheel_pants=1): """ Returns the predicted speed at full throttle. The MP_loss is the MP lost in the induction tract at full throttle at 2700 rpm at MSL. The default value is from the Lycoming power charts. The ram is the percentage of available ram recovery pressure that is achieved in the MP. """ press = SA.alt2press(altitude, press_units='in HG') MP_loss = MP_loss * (rpm / 2700.)**2 cas_guess = 300 error = 1 if mixture == 'econ': pwr_factor *= .86 # average power ratio to max power when at 50 deg LOP mixture elif mixture == 'pwr': pass else: raise ValueError('mixture must be one of "pwr" or "econ"') while error > 0.0001: dp = A.cas2dp(cas_guess, press_units='in HG') # print 'dp =', dp ram_press = ram * dp # print 'Ram rise =', ram_press MP = press - MP_loss + ram_press pwr = IO.pwr(rpm, MP, altitude, temp=temp, temp_units=temp_units) * pwr_factor # print 'MP =', MP, 'Power =', pwr tas = speed(prop, altitude, weight, pwr, rpm, temp = temp, \ temp_units = temp_units, rv = rv, wing_area = wing_area, \ speed_units = speed_units, wheel_pants = wheel_pants) cas = A.tas2cas(tas, altitude, temp=temp, temp_units=temp_units) error = M.fabs((cas - cas_guess) / cas) cas_guess = cas # print 'CAS =', cas, 'TAS =', tas # print "MP = %.3f" % MP # print "Pwr = %.2f" % pwr return tas
def MP_pred(tas, alt, rpm, rpm_base=2700., MP_loss=1.322, ram=0.5, temp='std'): press = SA.alt2press(alt, press_units='in HG') if temp == 'std': temp = SA.alt2temp(alt) dp = A.tas2dp(tas, alt, temp, speed_units='kt', alt_units='ft', temp_units='C', press_units='in HG') ram_press = ram * dp MP_loss = MP_loss * ( rpm / rpm_base )**1.85 # exponent from various online pressure drop calculators # MP_loss = MP_loss * (rpm / rpm_base) MP = press - MP_loss + ram_press # print "MP = %.3f" % MP return MP
def WOT_speed_orig(prop, altitude, weight = 1800, rpm = 2700, temp = 'std', \ temp_units = 'C', rv = '8', wing_area = 110, speed_units = 'kt' , \ MP_loss = 1.322, ram = 0.5, pwr_factor=1, mixture='pwr', \ wheel_pants=1): """ Returns the predicted speed at full throttle. The MP_loss is the MP lost in the induction tract at full throttle at 2700 rpm at MSL. The default value is from the Lycoming power charts. The ram is the percentage of available ram recovery pressure that is achieved in the MP. """ press = SA.alt2press(altitude, press_units = 'in HG') MP_loss = MP_loss * (rpm / 2700.) ** 2 cas_guess = 300 error = 1 if mixture == 'econ': pwr_factor *= .86 # average power ratio to max power when at 50 deg LOP mixture elif mixture == 'pwr': pass else: raise ValueError, 'mixture must be one of "pwr" or "econ"' while error > 0.0001: dp = A.cas2dp(cas_guess, press_units = 'in HG') # print 'dp =', dp ram_press = ram * dp # print 'Ram rise =', ram_press MP = press - MP_loss + ram_press pwr = IO.pwr(rpm, MP, altitude, temp = temp, temp_units = temp_units) * pwr_factor # print 'MP =', MP, 'Power =', pwr tas = speed(prop, altitude, weight, pwr, rpm, temp = temp, \ temp_units = temp_units, rv = rv, wing_area = wing_area, \ speed_units = speed_units, wheel_pants = wheel_pants) cas = A.tas2cas(tas, altitude, temp = temp, temp_units = temp_units) error = M.fabs((cas - cas_guess) / cas) cas_guess = cas # print 'CAS =', cas, 'TAS =', tas # print "MP = %.3f" % MP # print "Pwr = %.2f" % pwr return tas
def mach2cl( mach, altitude, weight, wing_area, load_factor=1, alt_units=default_alt_units, weight_units=default_weight_units, area_units=default_area_units, ): """ Returns the coefficient of lift, given equivalent mach, altitude, weight, and wing area. Load factor is an optional input. The load factor, if not provided, defaults to 1. Example: if the wing area is 110 square feet, altitude is 10,000 ft, the weight is 1800 lb, and the Mach number is 0.3 kt, in straight and level flight (so the load factor = 1), then: >>> Hp = 10000 >>> S = 110 >>> W = 1800 >>> Mach = 0.3 >>> mach2cl(Mach, Hp, W, S, weight_units='lb', area_units='ft**2') 0.17847495222708878 """ P = SA.alt2press(altitude, alt_units=alt_units, press_units="pa") wing_area = U.area_conv(wing_area, from_units=area_units, to_units="m**2") weight = U.wt_conv(weight, from_units=weight_units, to_units="kg") Cl = (weight * g * load_factor) / (0.7 * P * wing_area * mach**2) return Cl
def aoca(prop, altitude, weight = 1800, press_drop = 1.2, temp = 'std', \ climb = True): """ Returns speed for best climb or descent gradient and the gradient at that speed. """ MP = SA.alt2press(altitude) - press_drop pwr = IO.pwr(2700, MP, altitude, temp = temp) if climb == True: eass = range(550, 800, 1) else: eass = range(700, 1200, 1) aocs = [] if climb == True: for eas in eass: aocs.append((aoc(prop, altitude, eas/10., weight, pwr, 2700, temp = temp),eas)) else: for eas in eass: aocs.append((aoc(prop, altitude, eas/10., weight, 0, 2700, temp = temp),eas)) maoc, meas = max(aocs) return meas/10., maoc
def roc_vs_temp(prop, alt_max = 20000, alt_interval=2000, weight=1800, temps=[-20,0,20,40], pwr='max', \ pwr_factor=1.0, climb_speed='max', output='raw'): """ Returns the rates of climb at various temperatures """ if pwr == 'max': rpm = 2650 MP_max = 30 elif pwr == 'cc': rpm = 2500 MP_max = 25 elif pwr == 2500: rpm = 2500 MP_max = 30 else: raise ValueError, "pwr must be on of 'max', 'cc', or 2500" alt = 0 while alt<alt_max: press = SA.alt2press(alt) MP = press - (29.9213 - 28.6) cas = alt2roc_speed(alt, climb_speed = climb_speed) eas = A.cas2eas(cas, alt) # for temp in temps: # print temp, '\t\t\t', # print '\n', print '%.0f\t%.0f\t%.0f\t' % (weight, alt, cas), for temp in temps: # power = IO.pwr(rpm, MP, alt, temp) * pwr_factor power = alt2pwr(alt, rpm = rpm, MP_max = MP_max, temp = temp) ROC = roc(prop, alt, eas, weight, power, rpm, temp) /10 ROC = int('%.0f' % (ROC)) * 10 print '%.0f\t' % (ROC), print '\n' alt += alt_interval
def roc_vs_temp(prop, alt_max = 20000, alt_interval=2000, weight=1800, temps=[-20,0,20,40], pwr='max', \ pwr_factor=1.0, climb_speed='max', output='raw'): """ Returns the rates of climb at various temperatures """ if pwr == 'max': rpm = 2650 MP_max = 30 elif pwr == 'cc': rpm = 2500 MP_max = 25 elif pwr == 2500: rpm = 2500 MP_max = 30 else: raise ValueError("pwr must be on of 'max', 'cc', or 2500") alt = 0 while alt < alt_max: press = SA.alt2press(alt) MP = press - (29.9213 - 28.6) cas = alt2roc_speed(alt, climb_speed=climb_speed) eas = A.cas2eas(cas, alt) # for temp in temps: # print temp, '\t\t\t', # print '\n', print('%.0f\t%.0f\t%.0f\t' % (weight, alt, cas), end=' ') for temp in temps: # power = IO.pwr(rpm, MP, alt, temp) * pwr_factor power = alt2pwr(alt, rpm=rpm, MP_max=MP_max, temp=temp) ROC = roc(prop, alt, eas, weight, power, rpm, temp) / 10 ROC = int('%.0f' % (ROC)) * 10 print('%.0f\t' % (ROC), end=' ') print('\n') alt += alt_interval
def pwr_vs_alt_temp(temps): """ Returns a series of powers at full throttle and 2700 rpm at various temps 0 ft -20 0 20 40 ISA 213.4 205.4 198.3 191.9 200.0 2000 ft -20 0 20 40 ISA 197.3 189.9 183.3 177.4 186.2 4000 ft -20 0 20 40 ISA 182.4 175.6 169.5 164.0 173.4 6000 ft -20 0 20 40 ISA 167.8 161.5 155.9 150.9 160.6 8000 ft -20 0 20 40 ISA 154.1 148.3 143.2 138.6 148.6 10000 ft -20 0 20 40 ISA 141.3 136.1 131.3 127.1 137.3 12000 ft -20 0 20 40 ISA 129.3 124.5 120.2 116.3 126.6 14000 ft -20 0 20 40 ISA 118.2 113.8 109.8 106.2 116.5 16000 ft -20 0 20 40 ISA 107.4 103.4 99.8 96.6 106.7 18000 ft -20 0 20 40 ISA 97.3 93.7 90.4 87.5 97.4 20000 ft -20 0 20 40 ISA 87.7 84.4 81.5 78.9 88.5 """ alts = list(range(0, 22000, 2000)) for alt in alts: print(alt, 'ft') for temp in temps: print(temp, '\t', end=' ') print('ISA') for temp in temps: power = alt2pwr(alt, temp=temp) print('%.1f' % (power), '\t', end=' ') press = SA.alt2press(alt) MP = press - (29.9213 - 28.6) isa_pwr = IO.pwr(2700, MP, alt) print('%.1f' % (isa_pwr), '\n')
def pwr_vs_alt_temp(temps): """ Returns a series of powers at full throttle and 2700 rpm at various temps 0 ft -20 0 20 40 ISA 213.4 205.4 198.3 191.9 200.0 2000 ft -20 0 20 40 ISA 197.3 189.9 183.3 177.4 186.2 4000 ft -20 0 20 40 ISA 182.4 175.6 169.5 164.0 173.4 6000 ft -20 0 20 40 ISA 167.8 161.5 155.9 150.9 160.6 8000 ft -20 0 20 40 ISA 154.1 148.3 143.2 138.6 148.6 10000 ft -20 0 20 40 ISA 141.3 136.1 131.3 127.1 137.3 12000 ft -20 0 20 40 ISA 129.3 124.5 120.2 116.3 126.6 14000 ft -20 0 20 40 ISA 118.2 113.8 109.8 106.2 116.5 16000 ft -20 0 20 40 ISA 107.4 103.4 99.8 96.6 106.7 18000 ft -20 0 20 40 ISA 97.3 93.7 90.4 87.5 97.4 20000 ft -20 0 20 40 ISA 87.7 84.4 81.5 78.9 88.5 """ alts = range(0,22000, 2000) for alt in alts: print alt, 'ft' for temp in temps: print temp, '\t', print 'ISA' for temp in temps: power = alt2pwr(alt, temp = temp) print '%.1f' % (power), '\t', press = SA.alt2press(alt) MP = press - (29.9213 - 28.6) isa_pwr = IO.pwr(2700, MP, alt) print '%.1f' % (isa_pwr), '\n'
piece.append('2400'.center(cols)) piece.append('2200'.center(cols)) piece.append('2300'.center(cols)) piece.append('2400'.center(cols)) piece.append('2500'.center(cols)) full_line = '|'.join(piece) print('|' + full_line + '|') for alt in range(0, 16000, 1000): piece = [] piece.append(str(alt).rjust(col1)) temp = SA.alt2temp(alt, temp_units='F') temp = int(temp) piece.append(str(temp).rjust(col2)) press = SA.alt2press(alt) pwr = .55 * max_pwr for rpm in range(2100, 2500, 100): mp = float(O.pwr2mp(pwr, rpm, alt)) if press - mp < diff: piece.append('FT'.center(col2)) else: piece.append(str(round(mp, 1)).center(col2)) pwr = .65 * max_pwr for rpm in range(2100, 2500, 100): mp = float(O.pwr2mp(pwr, rpm, alt)) if press - mp < diff: piece.append('FT'.center(col2)) else:
def tas2ssec2(tas, ind_alt, oat, ias, std_alt=0, speed_units=default_speed_units, alt_units=default_alt_units, temp_units=default_temp_units, press_units=default_press_units): """ Return static source position error as speed error, pressure error and altitude error at sea level using speed course method. Returns delta_Vpc, delta_Ps and delta_Hpc tas = true airspeed determined by speed course method, or GPS ind_alt = pressure altitude, corrected for instrument error oat = outside air temperature, corrected for instrument error and ram temperature rise ias = indicated airspeed, corrected for instrument error std_alt = altitude to provide delta_Hpc for delta_Vpc = error in airspeed = calibrated airspeed - indicated airspeed corrected for instrument error delta_Ps = error in the pressure sensed by the static system = pressure sensed in the static system - ambient pressure delta_Hpc = altitude error at std_alt = actual altitude - altitude sensed by the static system Uses analysis method from USAF Test Pilot School. Unlike some other methods (e.g.. that in FAA AC 23-8B, or NTPS GPS_PEC.xls), this method provides an exact conversion from TAS to CAS (some other methods assume CAS = EAS), and it accounts for the effect of position error of altitude on the conversion from TAS to CAS (some other methods assume pressure altitude = indicated pressure altitude). """ tas = U.speed_conv(tas, speed_units, 'kt') ind_alt = U.length_conv(ind_alt, alt_units, 'ft') oat = U.temp_conv(oat, temp_units, 'C') M = A.tas2mach(tas, oat, temp_units='C', speed_units='kt') if M > 1: raise ValueError('This method only works for Mach < 1') delta_ic = SA.alt2press_ratio(ind_alt, alt_units='ft') qcic_over_Psl = A.cas2dp(ias, speed_units='kt', press_units=press_units) / U.press_conv( constants.P0, 'pa', to_units=press_units) qcic_over_Ps = qcic_over_Psl / delta_ic Mic = A.dp_over_p2mach(qcic_over_Ps) delta_mach_pc = M - Mic if Mic > 1: raise ValueError('This method only works for Mach < 1') deltaPp_over_Ps = (1.4 * delta_mach_pc * (Mic + delta_mach_pc / 2)) / ( 1 + 0.2 * (Mic + delta_mach_pc / 2)**2) deltaPp_over_qcic = deltaPp_over_Ps / qcic_over_Ps delta_Hpc = SA.alt2temp_ratio( std_alt, alt_units='ft') * deltaPp_over_Ps / 3.61382e-5 # experimental - alternate way to calculate delta_Hpc that gives same answer Ps = SA.alt2press(ind_alt, alt_units='ft', press_units=press_units) delta_Ps = deltaPp_over_Ps * Ps P_std = SA.alt2press(std_alt, alt_units='ft', press_units=press_units) deltaPs_std = deltaPp_over_Ps * P_std delta_Hpc2 = SA.press2alt(P_std - deltaPs_std, press_units=press_units) - std_alt delta_std_alt = SA.alt2press_ratio(std_alt, alt_units='ft') asl = U.speed_conv(constants.A0, 'm/s', 'kt') delta_Vpc_std_alt = deltaPp_over_Ps * delta_std_alt * asl**2 / ( 1.4 * ias * (1 + 0.2 * (ias / asl)**2)**2.5) actual_alt = SA.press2alt(Ps + delta_Ps, press_units=press_units, alt_units='ft') cas = A.tas2cas(tas, actual_alt, oat, speed_units='kt', alt_units='ft', temp_units='C') return delta_Vpc, delta_Ps, delta_Hpc, cas
def tas2ssec2(tas, ind_alt, oat, ias, std_alt = 0, speed_units=default_speed_units, alt_units=default_alt_units, temp_units=default_temp_units, press_units = default_press_units): """ Return static source position error as speed error, pressure error and altitude error at sea level using speed course method. Returns delta_Vpc, delta_Ps and delta_Hpc tas = true airspeed determined by speed course method, or GPS ind_alt = pressure altitude, corrected for instrument error oat = outside air temperature, corrected for instrument error and ram temperature rise ias = indicated airspeed, corrected for instrument error std_alt = altitude to provide delta_Hpc for delta_Vpc = error in airspeed = calibrated airspeed - indicated airspeed corrected for instrument error delta_Ps = error in the pressure sensed by the static system = pressure sensed in the static system - ambient pressure delta_Hpc = altitude error at std_alt = actual altitude - altitude sensed by the static system Uses analysis method from USAF Test Pilot School. Unlike some other methods (e.g.. that in FAA AC 23-8B, or NTPS GPS_PEC.xls), this method provides an exact conversion from TAS to CAS (some other methods assume CAS = EAS), and it accounts for the effect of position error of altitude on the conversion from TAS to CAS (some other methods assume pressure altitude = indicated pressure altitude). """ tas = U.speed_conv(tas, speed_units, 'kt') ind_alt = U.length_conv(ind_alt, alt_units, 'ft') oat = U.temp_conv(oat, temp_units, 'C') M = A.tas2mach(tas, oat, temp_units='C', speed_units='kt') if M > 1: raise ValueError, 'This method only works for Mach < 1' delta_ic = SA.alt2press_ratio(ind_alt, alt_units='ft') qcic_over_Psl = A.cas2dp(ias, speed_units='kt', press_units=press_units) / U.press_conv(constants.P0, 'pa', to_units=press_units) qcic_over_Ps = qcic_over_Psl / delta_ic Mic = A.dp_over_p2mach(qcic_over_Ps) delta_mach_pc = M - Mic if Mic > 1: raise ValueError, 'This method only works for Mach < 1' deltaPp_over_Ps = (1.4 * delta_mach_pc * (Mic + delta_mach_pc / 2)) / (1 + 0.2 * (Mic + delta_mach_pc / 2 )**2) deltaPp_over_qcic = deltaPp_over_Ps / qcic_over_Ps delta_Hpc = SA.alt2temp_ratio(std_alt, alt_units='ft') * deltaPp_over_Ps / 3.61382e-5 # experimental - alternate way to calculate delta_Hpc that gives same answer Ps = SA.alt2press(ind_alt, alt_units='ft', press_units=press_units) delta_Ps = deltaPp_over_Ps * Ps P_std = SA.alt2press(std_alt, alt_units='ft', press_units=press_units) deltaPs_std = deltaPp_over_Ps * P_std delta_Hpc2 = SA.press2alt(P_std - deltaPs_std, press_units = press_units) - std_alt delta_std_alt = SA.alt2press_ratio(std_alt, alt_units='ft') asl = U.speed_conv(constants.A0, 'm/s', 'kt') delta_Vpc_std_alt = deltaPp_over_Ps * delta_std_alt * asl**2 / (1.4 * ias * (1 + 0.2 * (ias / asl)**2)**2.5) actual_alt = SA.press2alt(Ps + delta_Ps, press_units = press_units, alt_units = 'ft') cas = A.tas2cas(tas, actual_alt, oat, speed_units='kt', alt_units='ft', temp_units='C') return delta_Vpc, delta_Ps, delta_Hpc, cas
piece.append('2400'.center(cols)) piece.append('2200'.center(cols)) piece.append('2300'.center(cols)) piece.append('2400'.center(cols)) piece.append('2500'.center(cols)) full_line = '|'.join(piece) print '|' + full_line + '|' for alt in range(0, 16000, 1000): piece = [] piece.append(str(alt).rjust(col1)) temp = SA.alt2temp(alt, temp_units = 'F') temp = int(temp) piece.append(str(temp).rjust(col2)) press = SA.alt2press(alt) pwr = .55 * max_pwr for rpm in range(2100, 2500, 100): mp = float(O.pwr2mp(pwr, rpm, alt)) if press - mp < diff: piece.append('FT'.center(col2)) else: piece.append(str(round(mp,1)).center(col2)) pwr = .65 * max_pwr for rpm in range(2100, 2500, 100): mp = float(O.pwr2mp(pwr, rpm, alt)) if press - mp < diff: piece.append('FT'.center(col2)) else: