Exemple #1
0
    def clean(self, mass, tas, alt, path_angle=0):
        """Compute drag at clean configuration (considering compressibility).

        Args:
            mass (int or ndarray): Mass of the aircraft (unit: kg).
            tas (int or ndarray): True airspeed (unit: kt).
            alt (int or ndarray): Altitude (unit: ft).
            path_angle (float or ndarray): Path angle (unit: degree). Defaults to 0.

        Returns:
            int: Total drag (unit: N).

        """

        cd0 = self.polar["clean"]["cd0"]
        k = self.polar["clean"]["k"]

        if self.wave_drag:
            mach_crit = self.polar["mach_crit"]
            mach = aero.tas2mach(tas * aero.kts, alt * aero.ft)

            dCdw = np.where(mach > mach_crit, 20 * (mach - mach_crit)**4, 0)
        else:
            dCdw = 0

        cd0 = cd0 + dCdw

        D = self._calc_drag(mass, tas, alt, cd0, k, path_angle)
        return D
Exemple #2
0
    def takeoff(self, tas, alt=None):
        """Calculate thrust during the takeoff.

        Args:
            tas (float or ndarray): True airspeed (kt).
            alt (float or ndarray): Altitude of the runway (ft). Defaults to 0.

        Returns:
            float or ndarray: Total thrust (unit: N).

        """
        mach = aero.tas2mach(tas*aero.kts, 0)

        eng_bpr = self.eng_bpr
        G0 = 0.0606 * self.eng_bpr + 0.6337

        if alt is None:
            # at sea level
            ratio = 1 - 0.377 * (1+eng_bpr) / np.sqrt((1+0.82*eng_bpr)*G0) * mach \
                       + (0.23 + 0.19 * np.sqrt(eng_bpr)) * mach**2

        else:
            # at certain altitude
            P = aero.pressure(alt * aero.ft)
            dP = P / aero.p0

            A = -0.4327 * dP**2 + 1.3855 * dP + 0.0472
            Z = 0.9106 * dP**3 - 1.7736 * dP**2 + 1.8697 * dP
            X = 0.1377 * dP**3 - 0.4374 * dP**2 + 1.3003 * dP

            ratio = A - 0.377 * (1+eng_bpr) / np.sqrt((1+0.82*eng_bpr)*G0) * Z * mach \
                  + (0.23 + 0.19 * np.sqrt(eng_bpr)) * X * mach**2

        F = ratio * self.eng_max_thrust * self.eng_number
        return F
Exemple #3
0
 def _sl2fl(self, tas, alt):
     M = aero.tas2mach(tas * aero.kts, alt * aero.ft)
     beta = np.exp(0.2 * (M**2))
     theta = (aero.temperature(alt * aero.ft) / 288.15) / beta
     delta = (1 - 0.0019812 * alt / 288.15)**5.255876 / np.power(beta, 3.5)
     ratio = (theta**3.3) / (delta**1.02)
     return beta, theta, delta, ratio
Exemple #4
0
    def climb(self, tas, alt, roc):
        """Calculate thrust during the climb.

        Args:
            tas (float or ndarray): True airspeed (kt).
            alt (float or ndarray): Altitude(ft)
            roc (float or ndarray): Vertical rate (ft/min).

        Returns:
            float or ndarray: Total thrust (unit: N).

        """
        roc = np.abs(roc)

        h = alt * aero.ft
        tas = np.where(tas < 10, 10, tas)

        mach = aero.tas2mach(tas * aero.kts, h)
        vcas = aero.tas2cas(tas * aero.kts, h)

        P = aero.pressure(h)
        P10 = aero.pressure(10000 * aero.ft)
        Pcr = aero.pressure(self.cruise_alt * aero.ft)

        # approximate thrust at top of climb (REF 2)
        Fcr = self.eng_cruise_thrust * self.eng_number
        vcas_ref = aero.mach2cas(self.cruise_mach, self.cruise_alt * aero.ft)

        # segment 3: alt > 30000:
        d = self._dfunc(mach / self.cruise_mach)
        b = (mach / self.cruise_mach)**(-0.11)
        ratio_seg3 = d * np.log(P / Pcr) + b

        # segment 2: 10000 < alt <= 30000:
        a = (vcas / vcas_ref)**(-0.1)
        n = self._nfunc(roc)
        ratio_seg2 = a * (P / Pcr)**(-0.355 * (vcas / vcas_ref) + n)

        # segment 1: alt <= 10000:
        F10 = Fcr * a * (P10 / Pcr)**(-0.355 * (vcas / vcas_ref) + n)
        m = self._mfunc(vcas / vcas_ref, roc)
        ratio_seg1 = m * (P / Pcr) + (F10 / Fcr - m * (P10 / Pcr))

        ratio = np.where(alt > 30000, ratio_seg3,
                         np.where(alt > 10000, ratio_seg2, ratio_seg1))

        F = ratio * Fcr
        return F
Exemple #5
0
 def mach(self) -> float:
     return aero.tas2mach(self.tas, self.altitude)
def main():
    # Debug output
    debug = open("./debug.log", 'w+')
    debug.write("altitude,vs,cas,tas,aoa,cl,cd,drag,lift,mass,thrust\n")
    debug.flush()
    # PID Setup
    a319 = performance.Performance("A319", False)
    a319_wrp = WRAP(ac="A319")
    autopilot = Autopilot()
    autothrust = Autothrust()
    a319.mass = 60_000.00
    a319.pitch = 0.0
    a319.gear = True
    a319.flaps = 1
    a319.pitch_target = 0.0
    a319.pitch_rate_of_change = 3.0
    target_alt = 6_000 * aero.ft
    # simulation varibale
    a319.phase = 0
    pitchs = []
    fd_pitchs = []
    alts = []
    vs = []
    cas = []
    times = []
    thrusts = []
    drags = []
    phases = []
    i = 0
    distance_0 = 0.0
    run = True
    # a319.run()
    # while run and a319.altitude >= 0:
    #     a319.run()
    #     if a319.cas > a319_wrp.takeoff_speed()["default"] and a319.phase == 0:
    #         a319.phase = 1
    #         a319.pitch_target = 15.0
    #     # When passing 100ft RA, the gear is up
    #     if a319.gear and (a319.altitude / aero.ft) > 100.0:
    #         a319.gear = False

    #     if a319.flaps > 0 and (a319.cas / aero.kts) > 210.0:
    #         a319.flaps = 0

    #     if (a319.altitude / aero.ft) > 1500.0 and\
    #        (a319.altitude / aero.ft) < 1550.0 and a319.phase < 2:
    #         a319.thrust_lever = 1.
    #         a319.phase = 2

    #     if (a319.altitude / aero.ft) > 3000.0 and a319.phase < 4:
    #         if a319.phase != 3:
    #             a319.phase = 3
    #             autopilot.VerticalSpeedHold(1000.0 * aero.fpm, target_alt)

    #     if a319.flaps == 0 and round(a319.cas / aero.kts) > 250\
    #             and a319.altitude < target_alt:
    #         if a319.phase != 4:
    #             a319.phase = 4
    #             speed_target = 250 * aero.kts
    #             autopilot.SpeedHold(speed_target, target_alt)
    #     #     # speed_target = 320 * aero.kts
    #     #     # if a319.altitude / aero.ft < 10_000:
    #     #     #     speed_target = 250 * aero.kts
    #     #     # elif a319.altitude >= aero.crossover_alt(320 * aero.kts, 0.78):
    #     #     #     speed_target = aero.mach2cas(0.78, a319.altitude)
    #     #     #     a319.thrust_lever = 1.0
    #     #     # if autopilot.active_mode != Autopilot.speed_hold \
    #     #     #         or autopilot.target != speed_target:
    #     #         # autopilot.SpeedHold(speed_target, target_alt)

    #     if a319.altitude + (a319.v_y * 30) >= target_alt:
    #         if a319.phase != 5:
    #             a319.phase = 5
    #             autopilot.AltitudeAquire(target_alt)
    #     if a319.altitude > target_alt + 61:
    #         if a319.phase != 7:
    #             a319.phase = 7
    #             autopilot.VerticalSpeedHold(-1000 * aero.fpm, target_alt)
    #             a319.thrust_lever = 0.0

    #     if target_alt - 61 <= a319.altitude <= target_alt + 61:
    #         if a319.phase != 6:
    #             a319.phase = 6
    #             autopilot.AltitudeHold(target_alt)
    #             if distance_0 == 0.0:
    #                 distance_0 = a319.distance_x
    #         if (a319.distance_x - distance_0) / aero.nm >= 5.0:
    #             run = False
    #     #     run = False
    #     #     continue
    #     if a319.cas / aero.kts >= 320:
    #         a319.tas = aero.cas2tas(320 * aero.kts, a319.altitude)
    #         # if a319.phase != 6:

    #     #     if a319.tas > aero.mach2tas(0.78, a319.altitude)\
    #     #             and autopilot.active_mode != Autopilot.mach_hold:
    #     #         autopilot.MachHold(0.78, target_alt)

    #     if a319.phase >= 0:
    #         if (a319.pitch > 0 or a319.altitude > 0) \
    #                 and (round((a319.altitude / aero.ft) / 10) * 10) \
    #                 % 5000 == 0:
    #             debug.write(f"{a319.altitude / aero.ft},{a319.vs},"
    #                         f"{a319.cas / aero.kts},{a319.tas/ aero.kts},"
    #                         f"{a319.aoa},{a319.cl},{a319.cd},{a319.drag},"
    #                         f"{a319.lift},{a319.mass},{a319.thrust}\n")
    #             debug.flush()

    #         if a319.phase < 7 and a319.altitude > 10_000 * aero.ft:
    #             a319.thrust_lever = 1.0
    #         if a319.phase == 7:
    #             a319.thrust_lever = 0.0
    #         mach = aero.tas2mach(a319.tas, a319.altitude)
    #         if autopilot.active_mode is not None:
    #             a319.pitch_target = autopilot.run(a319.cas,
    #                                               a319.v_y,
    #                                               a319.altitude,
    #                                               a319.pitch,
    #                                               mach)
    #             a319.pitch = a319.pitch_target
    a319.tas = aero.cas2tas(200 * aero.kts, 0.0)
    a319.pitch = 0.0
    a319.aoa = 0.0
    a319.altitude = 5000.0 * aero.ft
    a319.flaps = 1
    for e in range(60):
        a319.run()
        # alts.append(int(round(a319.altitude / aero.ft)))
        # vs.append(int(a319.vs))
        # cas.append(a319.cas / aero.kts)
        # pitchs.append(a319.pitch)
        # thrusts.append(a319.thrust_lever)
        # times.append(e / 60.0)
    i = 61
    target_alt = 1000.0 * aero.ft
    autopilot.SpeedHold(180 * aero.kts, target_alt)
    # spd_target = 320 * aero.kts
    # autothrust.SpeedHold(spd_target)
    run = True
    a319.thrust_lever = 0.0
    while not (target_alt + 1 > a319.altitude > target_alt - 1):
        a319.run()
        mach = tas2mach(a319.tas, a319.altitude)
        a319.pitch_target = autopilot.run(a319.cas, a319.v_y, a319.altitude,
                                          a319.pitch, mach)
        a319.pitch = a319.pitch_target
        # if a319.altitude < (12_000 * aero.ft)\
        #         and autopilot.target != 220 * aero.kts:
        #     autopilot.target = 220 * aero.kts
        if autopilot.active_mode == autopilot.alt_aquire:
            if autothrust.active_mode is None:
                autothrust.SpeedHold(180 * aero.kts)
            a319.thrust_lever = autothrust.run(a319.cas)

        print(f"{a319.phase} : {a319.altitude / aero.ft:02f}",
              f"- {a319.vs:02f} - {a319.cas / aero.kts:02f} - ",
              f"{mach:0.3f} - {a319.aoa:0.2f} ",
              f"{a319.pitch:02f} / {a319.pitch_target:02f} - ",
              f"{a319.cl:04f} - {a319.cd:04f} - {a319.thrust_lever:03f}")
        alts.append(int(round(a319.altitude / aero.ft)))
        vs.append(int(a319.vs))
        cas.append(a319.cas / aero.kts)
        pitchs.append(a319.pitch)
        times.append(i / 60.0)
        fd_pitchs.append(a319.pitch_target)
        thrusts.append(a319.thrust_lever)
        drags.append(a319.drag)
        phases.append(a319.phase)
        i += 1

    print(f"Cas End  = {max(cas)}")
    draw(times[60:], vs[60:], alts[60:], cas[60:], pitchs[60:], [],
         thrusts[60:], [], [])