예제 #1
0
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
예제 #2
0
def tas2ssec(tas, alt, oat, ias, 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.
    
    Returns delta_Vpc, delta_Ps, delta_Hpc and Vc
    
    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 sea level = actual altitude - altitude sensed by the static system
    
    Vc = calibrated airspeed at the test point
    """
    P0 = U.press_conv(constants.P0, from_units = 'pa', to_units = press_units)
    cas = A.tas2cas(tas, alt, oat, speed_units=speed_units, alt_units=alt_units, temp_units=temp_units)
    delta_Vpc = cas - ias
    
    qcic = A.cas2dp(ias, speed_units=speed_units, press_units =press_units)
    qc = A.cas2dp(cas, speed_units=speed_units, press_units = press_units)
    delta_Ps = qc - qcic

    delta_Hpc = SA.press2alt(P0 - delta_Ps, press_units  = press_units) 
    
#     print 'Vc = %.1f, delta_vpc = %.1f, delta_ps = %.1f, delta_hpc = %.0f' % (cas, delta_Vpc, delta_Ps, delta_Hpc)
    
    return delta_Vpc, delta_Ps, delta_Hpc, cas
예제 #3
0
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
예제 #4
0
    def test_02(self):

        # 400 kt at 30000, temp -70 deg F
        # truth value from NASA RP 1046 + correction for non-standard temp

        Value = A.tas2cas(586.266, 30000, -70, temp_units='F')
        Truth = 400
        self.assertTrue(RE(Value, Truth) <= 3e-5)
예제 #5
0
    def test_01(self):

        # 400 kt at 30000, std temp
        # truth value from NASA RP 1046

        Value = A.tas2cas(602.6, 30000)
        Truth = 400
        self.assertTrue(RE(Value, Truth) <= 3e-5)
예제 #6
0
    def test_02(self):

        # 400 kt at 30000, temp -70 deg F
        # truth value from NASA RP 1046 + correction for non-standard temp

        Value = A.tas2cas(586.266, 30000, -70, temp_units='F')
        Truth = 400
        self.failUnless(RE(Value, Truth) <= 3e-5)
예제 #7
0
    def test_01(self):

        # 400 kt at 30000, std temp
        # truth value from NASA RP 1046

        Value = A.tas2cas(602.6, 30000)
        Truth = 400
        self.failUnless(RE(Value, Truth) <= 3e-5)
예제 #8
0
def gps2stall(GS,
              TK,
              Hp,
              T,
              temp_units='C',
              alt_units=default_alt_units,
              speed_units=default_speed_units,
              GPS_units=default_speed_units):
    """
    Return the CAS at the stall, given four GPS ground speeds, GPS tracks, 
    altitude and temperature.
    
    speed_units = CAS units.  May be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'.
    GS_units = GPS ground speed units.  'kt', 'mph', 'km/h', 'm/s' and 'ft/s'.
    HP = pressure altitude.  May be feet ('ft'), metres ('m'), kilometres ('km'), 
    statute miles, ('sm') or nautical miles ('nm').

    The temperature may be in deg C, F, K or R. 

    If the units are not specified, the units in default_units.py are used.
    
    Conduct four stalls, in a four sided box pattern, with all stalls at the same
    pressure altitude.  The data reduction algorithm calculates the TAS using Doug
    Gray's GPS to TAS method, using four different combinations of three legs.  If
    the data quality is high, all four TAS values will be similar, with a low standard
    deviation.
    
    The TAS at the stall is converted to CAS, using pressure altitude and 
    temperature.
    
    Returns CAS and standard deviation of the CAS value.
    
    Examples:
    
    >>> gps2stall([44, 104, 157, 131], [258, 29, 91, 150], 7000, 14, temp_units='F', GPS_units='km/h')
    (50.322235245211225, 0.6583323098888626)

    """

    tas, std_dev = SSEC.gps2tas(GS, TK, verbose=1)
    tas = U.speed_conv(tas, from_units=GPS_units, to_units=speed_units)
    std_dev = U.speed_conv(std_dev, from_units=GPS_units, to_units=speed_units)
    cas = A.tas2cas(tas,
                    Hp,
                    T,
                    temp_units=temp_units,
                    alt_units=alt_units,
                    speed_units=speed_units)
    std_dev = std_dev * cas / tas  # factor standard deviation to reference CAS vs TAS

    return cas, std_dev
예제 #9
0
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
예제 #10
0
def gps2stall(GS, TK, Hp, T, temp_units='C', alt_units=default_alt_units, speed_units=default_speed_units, GPS_units=default_speed_units):
    """
    Return the CAS at the stall, given four GPS ground speeds, GPS tracks, 
    altitude and temperature.
    
    speed_units = CAS units.  May be 'kt', 'mph', 'km/h', 'm/s' and 'ft/s'.
    GS_units = GPS ground speed units.  'kt', 'mph', 'km/h', 'm/s' and 'ft/s'.
    HP = pressure altitude.  May be feet ('ft'), metres ('m'), kilometres ('km'), 
    statute miles, ('sm') or nautical miles ('nm').

    The temperature may be in deg C, F, K or R. 

    If the units are not specified, the units in default_units.py are used.
    
    Conduct four stalls, in a four sided box pattern, with all stalls at the same
    pressure altitude.  The data reduction algorithm calculates the TAS using Doug
    Gray's GPS to TAS method, using four different combinations of three legs.  If
    the data quality is high, all four TAS values will be similar, with a low standard
    deviation.
    
    The TAS at the stall is converted to CAS, using pressure altitude and 
    temperature.
    
    Returns CAS and standard deviation of the CAS value.
    
    Examples:
    
    >>> gps2stall([44, 104, 157, 131], [258, 29, 91, 150], 7000, 14, temp_units='F', GPS_units='km/h')
    (50.322235245211225, 0.6583323098888626)

    """


    tas, std_dev = SSEC.gps2tas(GS, TK, verbose=1)
    tas = U.speed_conv(tas, from_units=GPS_units, to_units=speed_units)
    std_dev = U.speed_conv(std_dev, from_units=GPS_units, to_units=speed_units)
    cas = A.tas2cas(tas, Hp, T, temp_units=temp_units, alt_units=alt_units, speed_units=speed_units)
    std_dev = std_dev * cas / tas # factor standard deviation to reference CAS vs TAS

    return cas, std_dev
예제 #11
0
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
예제 #12
0
def tas2ssec(tas,
             alt,
             oat,
             ias,
             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.
    
    Returns delta_Vpc, delta_Ps, delta_Hpc and Vc
    
    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 sea level = actual altitude - altitude sensed by the static system
    
    Vc = calibrated airspeed at the test point
    """
    P0 = U.press_conv(constants.P0, from_units='pa', to_units=press_units)
    cas = A.tas2cas(tas,
                    alt,
                    oat,
                    speed_units=speed_units,
                    alt_units=alt_units,
                    temp_units=temp_units)
    delta_Vpc = cas - ias

    qcic = A.cas2dp(ias, speed_units=speed_units, press_units=press_units)
    qc = A.cas2dp(cas, speed_units=speed_units, press_units=press_units)
    delta_Ps = qc - qcic

    delta_Hpc = SA.press2alt(P0 - delta_Ps, press_units=press_units)

    #     print 'Vc = %.1f, delta_vpc = %.1f, delta_ps = %.1f, delta_hpc = %.0f' % (cas, delta_Vpc, delta_Ps, delta_Hpc)

    return delta_Vpc, delta_Ps, delta_Hpc, cas
예제 #13
0
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
예제 #14
0
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
예제 #15
0
def descent_data(prop, weight=1600., alt_max=20000., fuel_units='USG', \
    alt_interval=500., isa_dev=0, temp_units='C', rv='8',  wing_area=110., \
    tas=180., ROD=-500., angle='', speed_units='kt', rpm=2100., sfc=0.45, output='raw'):
    """
    Returns a table of descent performance vs altitude.

    The items in each row of the table are altitude, time, fuel burned and distance.
    Time is in units of minutes, rounded to the nearest half minute.
    Fuel units are selectable, with a default of USG.
    Distances are in nm.
    
    The output may be specified as raw, latex (a LaTeX table for the POH), or array.
    
    tas is the TAS in descent (overridden by the angle, if the angle is provided).
    angle is the flight path angle in degrees.
    """
    tas_fts = U.speed_conv(tas, speed_units, 'ft/s')

    if angle:
        ROD = tas_fts * 60 * M.sin(angle * M.pi / 180)
        
    rod_fts = ROD / 60

    tas = U.speed_conv(tas, speed_units, 'kt')
    
    alt = alt_max + alt_interval
    temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
    time = 0
    fuel_used = 0
    dist = 0
    
    if output == 'raw':
        print S.center('Altitude', 10),
        print S.center('ROD', 10),
        print S.center('Time', 10),
        print S.center('Fuel Used', 10),
        print S.center('Dist', 10),
        print S.center('Speed', 10)
        
        print S.center('(ft)', 10),
        print S.center('(ft/mn)', 10),
        print S.center('(mn)', 10),
        f_units = '(' + fuel_units + ')'
        print S.center(f_units, 10),
        print S.center('(nm)', 10),
        print S.center('(KCAS)', 10)
        
        # # data for max altitude
        # print S.rjust(locale.format('%.0f', alt_max, True), 7),
        # print S.rjust(locale.format('%.0f', round(ROD / 10.) * 10, True), 10),
        # print S.rjust('%.1f' % (0), 10),
        # print S.rjust('%.1f' % (fuel_used), 10),
        # print S.rjust('%.1f' % (dist), 10),
        # print S.rjust('%3d' % (A.tas2cas(tas, alt_max, temp, temp_units=temp_units)), 10)

    # elif output == 'latex':
    #     # temp = 15 + isa_dev
    #     MSL_line = []
    #     MSL_line.append(str(locale.format('%.0f', weight, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(locale.format('%.0f', temp)))
    #     MSL_line.append(str(locale.format('%.0f', A.tas2cas(tas, alt, temp, temp_units=temp_units))))
    #     MSL_line.append(str(locale.format('%.0f', round(ROD / 10.) * 10, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(fuel_used))
    #     MSL_line.append(str(dist))
    #     
    #     print '&'.join(MSL_line) + '\\\\'
    #     print '\\hline'
    # elif output == 'array':
    #     # no header rows, but make blank array
    #     array = [[alt_max,0,0,0]]
        

    alts = []
    RODs = []
    times_temp = []
    CASs = []
    dists_temp = []
    fuel_useds_temp = []
    temps = []

    calc_alt = alt_max - alt_interval / 2.
    while alt > 0:
        temp = SA.isa2temp(isa_dev, alt, temp_units = temp_units)
        eas = A.tas2eas(tas, alt)
        drag = FT.eas2drag(eas, weight)
        pwr_level_flt = tas_fts * drag / 550
        thrust_power = pwr_level_flt + FT.Pexcess_vs_roc(weight, ROD)
        prop_eff = PM.prop_eff(prop, thrust_power, rpm, tas, alt, temp, temp_units=temp_units)
        calc_pwr = thrust_power / prop_eff        
        #fuel_flow = IO.pwr2ff(calc_pwr, rpm, ff_units = 'lb/hr')
        fuel_flow = calc_pwr * sfc 
        # print "Level flt pwr = %.1f, thrust power = %.1f, prop eff = %.3f, fuel flow = %.3f" % (pwr_level_flt, thrust_power, prop_eff, fuel_flow)
        slice_time = alt_interval / rod_fts * -1.
        slice_dist = tas_fts * slice_time
        slice_fuel = fuel_flow * slice_time / 3600
        fuel_used += slice_fuel
        fuel_out = (U.avgas_conv(fuel_used, from_units = 'lb', \
            to_units = fuel_units))
        weight -= slice_fuel
        alt -= alt_interval
        cas_out = A.tas2cas(tas, alt, temp, temp_units=temp_units)
        temp_out = SA.isa2temp(isa_dev, alt)
        time += slice_time / 60.
        dist += slice_dist / 6076.115

        alts.append(alt)
        CASs.append(cas_out)
        RODs.append(ROD)
        times_temp.append(time)
        fuel_useds_temp.append(fuel_out)
        dists_temp.append(dist)
        temps.append(temp_out)
        
        calc_alt += alt_interval
        
    alts.reverse()
    CASs.reverse()
    RODs.reverse()
    temps.reverse()
    
    times = []
    fuel_useds = []
    dists = []
    
    for n, time in enumerate(times_temp):
        times.append(times_temp[-1] - time)
        fuel_useds.append(fuel_useds_temp[-1] - fuel_useds_temp[n])
        dists.append(dists_temp[-1] - dists_temp[n])
        
    times.reverse()
    fuel_useds.reverse()
    dists.reverse()
    
    if output == 'raw':
        for n, alt in enumerate(alts):            
            print S.rjust(locale.format('%.0f', alt, True), 7),
            # calculate ROC at the displayed altitude
            print S.rjust(locale.format('%.0f', RODs[n], True), 10),
            print S.rjust('%.1f' % (times[n]), 10),
            print S.rjust('%.1f' % (fuel_useds[n]), 10),
            print S.rjust('%.1f' % (dists[n]), 10),
            print S.rjust('%3d' % (int(CASs[n])), 10)
    elif output == 'latex':
        for n, alt in enumerate(alts):                    
            line = []
            line.append(str(locale.format('%.0f', alt, True)))
            line.append(str(locale.format('%.0f', round(temps[n]))))
            line.append(str(locale.format('%.0f', CASs[n])))
            line.append(str(locale.format('%.0f', round(RODs[n] / 10.) * 10, True)))
            line.append(str(locale.format('%.0f', times[n])))
            line.append(str(locale.format('%.1f', fuel_useds[n])))
            line.append(str(locale.format('%.0f', dists[n])))
            print '&' + '&'.join(line) + '\\\\'
            print '\\hline'
    elif output == 'array':
        array = []
        for n, alt in enumerate(alts):
            array.append([alt, times[n], fuel_useds[n], dists[n]])
        return array
예제 #16
0
def descent_data(prop, weight=1600., alt_max=20000., fuel_units='USG', \
    alt_interval=500., isa_dev=0, temp_units='C', rv='8',  wing_area=110., \
    tas=180., ROD=-500., angle='', speed_units='kt', rpm=2100., sfc=0.45, output='raw'):
    """
    Returns a table of descent performance vs altitude.

    The items in each row of the table are altitude, time, fuel burned and distance.
    Time is in units of minutes, rounded to the nearest half minute.
    Fuel units are selectable, with a default of USG.
    Distances are in nm.
    
    The output may be specified as raw, latex (a LaTeX table for the POH), or array.
    
    tas is the TAS in descent (overridden by the angle, if the angle is provided).
    angle is the flight path angle in degrees.
    """
    tas_fts = U.speed_conv(tas, speed_units, 'ft/s')

    if angle:
        ROD = tas_fts * 60 * M.sin(angle * M.pi / 180)

    rod_fts = ROD / 60

    tas = U.speed_conv(tas, speed_units, 'kt')

    alt = alt_max + alt_interval
    temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
    time = 0
    fuel_used = 0
    dist = 0

    if output == 'raw':
        print(S.center('Altitude', 10), end=' ')
        print(S.center('ROD', 10), end=' ')
        print(S.center('Time', 10), end=' ')
        print(S.center('Fuel Used', 10), end=' ')
        print(S.center('Dist', 10), end=' ')
        print(S.center('Speed', 10))

        print(S.center('(ft)', 10), end=' ')
        print(S.center('(ft/mn)', 10), end=' ')
        print(S.center('(mn)', 10), end=' ')
        f_units = '(' + fuel_units + ')'
        print(S.center(f_units, 10), end=' ')
        print(S.center('(nm)', 10), end=' ')
        print(S.center('(KCAS)', 10))

        # # data for max altitude
        # print S.rjust(locale.format('%.0f', alt_max, True), 7),
        # print S.rjust(locale.format('%.0f', round(ROD / 10.) * 10, True), 10),
        # print S.rjust('%.1f' % (0), 10),
        # print S.rjust('%.1f' % (fuel_used), 10),
        # print S.rjust('%.1f' % (dist), 10),
        # print S.rjust('%3d' % (A.tas2cas(tas, alt_max, temp, temp_units=temp_units)), 10)

    # elif output == 'latex':
    #     # temp = 15 + isa_dev
    #     MSL_line = []
    #     MSL_line.append(str(locale.format('%.0f', weight, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(locale.format('%.0f', temp)))
    #     MSL_line.append(str(locale.format('%.0f', A.tas2cas(tas, alt, temp, temp_units=temp_units))))
    #     MSL_line.append(str(locale.format('%.0f', round(ROD / 10.) * 10, True)))
    #     MSL_line.append('0')
    #     MSL_line.append(str(fuel_used))
    #     MSL_line.append(str(dist))
    #
    #     print '&'.join(MSL_line) + '\\\\'
    #     print '\\hline'
    # elif output == 'array':
    #     # no header rows, but make blank array
    #     array = [[alt_max,0,0,0]]

    alts = []
    RODs = []
    times_temp = []
    CASs = []
    dists_temp = []
    fuel_useds_temp = []
    temps = []

    calc_alt = alt_max - alt_interval / 2.
    while alt > 0:
        temp = SA.isa2temp(isa_dev, alt, temp_units=temp_units)
        eas = A.tas2eas(tas, alt)
        drag = FT.eas2drag(eas, weight)
        pwr_level_flt = tas_fts * drag / 550
        thrust_power = pwr_level_flt + FT.Pexcess_vs_roc(weight, ROD)
        prop_eff = PM.prop_eff(prop,
                               thrust_power,
                               rpm,
                               tas,
                               alt,
                               temp,
                               temp_units=temp_units)
        calc_pwr = thrust_power / prop_eff
        #fuel_flow = IO.pwr2ff(calc_pwr, rpm, ff_units = 'lb/hr')
        fuel_flow = calc_pwr * sfc
        # print "Level flt pwr = %.1f, thrust power = %.1f, prop eff = %.3f, fuel flow = %.3f" % (pwr_level_flt, thrust_power, prop_eff, fuel_flow)
        slice_time = alt_interval / rod_fts * -1.
        slice_dist = tas_fts * slice_time
        slice_fuel = fuel_flow * slice_time / 3600
        fuel_used += slice_fuel
        fuel_out = (U.avgas_conv(fuel_used, from_units = 'lb', \
            to_units = fuel_units))
        weight -= slice_fuel
        alt -= alt_interval
        cas_out = A.tas2cas(tas, alt, temp, temp_units=temp_units)
        temp_out = SA.isa2temp(isa_dev, alt)
        time += slice_time / 60.
        dist += slice_dist / 6076.115

        alts.append(alt)
        CASs.append(cas_out)
        RODs.append(ROD)
        times_temp.append(time)
        fuel_useds_temp.append(fuel_out)
        dists_temp.append(dist)
        temps.append(temp_out)

        calc_alt += alt_interval

    alts.reverse()
    CASs.reverse()
    RODs.reverse()
    temps.reverse()

    times = []
    fuel_useds = []
    dists = []

    for n, time in enumerate(times_temp):
        times.append(times_temp[-1] - time)
        fuel_useds.append(fuel_useds_temp[-1] - fuel_useds_temp[n])
        dists.append(dists_temp[-1] - dists_temp[n])

    times.reverse()
    fuel_useds.reverse()
    dists.reverse()

    if output == 'raw':
        for n, alt in enumerate(alts):
            print(S.rjust(locale.format('%.0f', alt, True), 7), end=' ')
            # calculate ROC at the displayed altitude
            print(S.rjust(locale.format('%.0f', RODs[n], True), 10), end=' ')
            print(S.rjust('%.1f' % (times[n]), 10), end=' ')
            print(S.rjust('%.1f' % (fuel_useds[n]), 10), end=' ')
            print(S.rjust('%.1f' % (dists[n]), 10), end=' ')
            print(S.rjust('%3d' % (int(CASs[n])), 10))
    elif output == 'latex':
        for n, alt in enumerate(alts):
            line = []
            line.append(str(locale.format('%.0f', alt, True)))
            line.append(str(locale.format('%.0f', round(temps[n]))))
            line.append(str(locale.format('%.0f', CASs[n])))
            line.append(
                str(locale.format('%.0f',
                                  round(RODs[n] / 10.) * 10, True)))
            line.append(str(locale.format('%.0f', times[n])))
            line.append(str(locale.format('%.1f', fuel_useds[n])))
            line.append(str(locale.format('%.0f', dists[n])))
            print('&' + '&'.join(line) + '\\\\')
            print('\\hline')
    elif output == 'array':
        array = []
        for n, alt in enumerate(alts):
            array.append([alt, times[n], fuel_useds[n], dists[n]])
        return array