示例#1
0
    def __init__(self, ac, eng=None):
        """Intitialize the generator.

        Args:
            ac (string): Aircraft type.
            eng (string): Engine type. Leave empty for default engine type in OpenAP.

        Returns:
            dict: flight trajectory

        """
        super(Generator, self).__init__()

        self.ac = ac
        self.acdict = prop.aircraft(self.ac)

        if eng is None:
            self.eng = self.acdict['engine']['default']
        else:
            self.eng = eng
        self.engdict = prop.engine(self.eng)

        self.wrap = WRAP(self.ac)
        # self.thrust = Thrust(self.ac, self.eng)
        # self.drag = Drag(self.ac)
        # self.fuelflow = Thrust(self.ac, self.eng)

        # for noise generation
        self.sigma_v = 0
        self.sigma_vs = 0
        self.sigma_h = 0
        self.sigma_s = 0
示例#2
0
 def __init__(self, icao_type: str, callsign: str) -> None:
     self.performance = Performance(icao_type)
     self.autoThrust = Autothrust()
     self.autoPilot = Autopilot()
     self.latitude = 0.0
     self.longitude = 0.0
     self.ground_level = 0.0
     self.callsign = callsign
     self.takeoff = False
     self.wrap = WRAP(ac=icao_type)
     self.target_alt = 6_000 * aero.ft
     self.id = 0
               f"{self.drag},{self.thrust},{self.t_d},{self.pitch},"\
               f"{self.fpa},{self.aoa},{self.Q},{self.acc_x},{self.acc_y},"\
               f"{self.distance_x},{self.d_x},{self.d_y},{self.phase},"\
               f"{self.cd},{self.drag0},{self.gear},{self.flaps},{self.cl},"\
               f"{self.lift},{self.weight},{self.l_w},{self.thrust_lever},"\
               f"{self.altitude / aero.ft},{self.g},{self.pitch_target}\n"

    def __get_header(self):
        return "Mass,Altitude,Pressure,Density,Temperature,Cas,Tas,Vy,VS,"\
               "Drag,Thrust,T-D,Pitch,FPA,AOA,Q,AccelerationX,AccelerationY,"\
               "DistanceX,Dx,Dy,Phase,Cd,Cd0,Gear,Flaps,Cl,Lift,Weight,L-W,"\
               "Thrust Limit,Altitude FT,Gravity,Target Pitch\n"


if __name__ == "__main__":
    from openap import WRAP

    a319 = Performance("A319")
    a319_wrp = WRAP(ac="A319")
    a319.cas = a319_wrp.takeoff_speed()["default"]
    a319.tas = aero.cas2tas(a319.cas, a319.altitude)
    a319.pitch = 15.0
    a319.v_y = 2000 * aero.fpm
    a319.gear = True
    a319.flaps = 2
    print(a319.v_y)
    print("Starting")
    for i in range(10):
        a319.run()
    print("Finished")
示例#4
0
class Aircraft:
    """Represent an aircraft"""
    def __init__(self, icao_type: str, callsign: str) -> None:
        self.performance = Performance(icao_type)
        self.autoThrust = Autothrust()
        self.autoPilot = Autopilot()
        self.latitude = 0.0
        self.longitude = 0.0
        self.ground_level = 0.0
        self.callsign = callsign
        self.takeoff = False
        self.wrap = WRAP(ac=icao_type)
        self.target_alt = 6_000 * aero.ft
        self.id = 0

    def get_ap_vert_mode(self) -> dict:
        return {
            "Altitude Aquire": Autopilot.alt_aquire,
            "Altitude Hold": Autopilot.alt_hold,
            "Speed Hold": Autopilot.speed_hold,
            "Mach Hold": Autopilot.mach_hold,
            "Vert Speed Hold": Autopilot.vs_hold
        }

    def set_ap_vert_mode(self, mode: int, target: float,
                         target_altitude: float) -> bool:
        if mode == Autopilot.alt_aquire:
            self.autoPilot.AltitudeAquire(target_altitude)
        elif mode == Autopilot.alt_hold:
            self.autoPilot.AltitudeHold(target_altitude)
        elif mode == Autopilot.speed_hold:
            self.autoPilot.SpeedHold(target, target_altitude)
        elif mode == Autopilot.mach_hold:
            self.autoPilot.MachHold(target, target_altitude)
        elif mode == Autopilot.vs_hold:
            self.autoPilot.VerticalSpeedHold(target, target_altitude)
        else:
            return False
        return True

    def run(self) -> int:
        self.performance.run()
        if self.takeoff:
            if self.performance.pitch < self.target_to_pitch and\
                    self.cas() >= self.wrap.takeoff_speed()["default"]:
                self.performance.pitch += 3.0 * self.performance.dt
            if self.performance.pitch >= self.target_to_pitch and\
                    self.cas() >= self.wrap.takeoff_speed()["default"]:
                self.takeoff = False
                self.autoPilot.SpeedHold(self.cas(), self.target_alt)

        if self.autoPilot.active_mode is not None:
            self.performance.pitch = self.autoPilot.run(self.cas(),
                                                        self.vertical_speed(),
                                                        self.altitude(),
                                                        self.pitch(),
                                                        self.mach())
        if self.autoThrust.active_mode is not None:
            self.performance.thrust_lever = self.autoThrust.run(self.cas())

    @property
    def pitch(self) -> float:
        return self.performance.pitch

    @property
    def altitude(self) -> float:
        return self.performance.altitude

    @property
    def tas(self) -> float:
        return self.performance.tas

    @property
    def cas(self) -> float:
        return self.performance.cas

    @property
    def mach(self) -> float:
        return aero.tas2mach(self.tas, self.altitude)

    @property
    def vertical_speed(self) -> float:
        return self.performance.v_y

    def angle_of_attack(self) -> float:
        return self.performance.aoa

    @property
    def mass(self) -> float:
        return self.performance.mass

    @mass.setter
    def mass(self, value: float) -> None:
        self.performance.mass = value

    def create(self, position: tuple, mass: float,
               ground_level: float = 0.0, altitude: float = 0.0,
               cas: float = 0.0, takeoff: bool = False,
               target_alt: float = None) -> bool:
        self.performance.mass = mass
        self.latitude, self.longitude = position
        self.ground_level = ground_level
        self.performance.altitude = altitude
        self.performance.cas = cas
        self.performance.tas = aero.cas2tas(cas, self.performance.altitude)
        self.mach = aero.cas2mach(self.performance.cas,
                                  self.performance.altitude)
        if target_alt is not None:
            self.target_alt = target_alt
        elif not takeoff and altitude > 0 and altitude > ground_level:
            self.target_alt = altitude
        elif not takeoff:
            takeoff = True
        if not takeoff:
            self.autoPilot.AltitudeHold(self.altitude)

    def set_target_alt(self, altitude: float) -> None:
        self.target_alt = altitude
示例#5
0
class Generator(object):
    """Generate trajectory using WRAP model."""
    def __init__(self, ac, eng=None):
        """Intitialize the generator.

        Args:
            ac (string): Aircraft type.
            eng (string): Engine type. Leave empty for default engine type in OpenAP.

        Returns:
            dict: flight trajectory

        """
        super(Generator, self).__init__()

        self.ac = ac
        self.acdict = prop.aircraft(self.ac)

        if eng is None:
            self.eng = self.acdict['engine']['default']
        else:
            self.eng = eng
        self.engdict = prop.engine(self.eng)

        self.wrap = WRAP(self.ac)
        # self.thrust = Thrust(self.ac, self.eng)
        # self.drag = Drag(self.ac)
        # self.fuelflow = Thrust(self.ac, self.eng)

        # for noise generation
        self.sigma_v = 0
        self.sigma_vs = 0
        self.sigma_h = 0
        self.sigma_s = 0

    def enable_noise(self):
        """Adding noise to the generated trajectory.

        The noise model is based on ADS-B Version 1&2, NACv=3 and NACp=10
        """
        self.sigma_v = 0.5
        self.sigma_vs = 0.75
        self.sigma_h = 7.5
        self.sigma_s = 5

    def climb(self, **kwargs):
        """Generate climb trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_cl (int): Constaant CAS for climb (kt).
            **mach_const_cl (float): Constaant Mach for climb (-).
            **h_cr (int): Target cruise altitude (km).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: Flight trajectory.

        """
        dt = kwargs.get('dt', 1)
        random = kwargs.get('random', False)

        a_tof = self.wrap.takeoff_acceleration()['default']
        v_tof = self.wrap.takeoff_speed()['default']

        if random:
            cas_const = kwargs.get(
                'cas_const_cl',
                np.random.uniform(self.wrap.climb_const_vcas()['minimum'],
                                  self.wrap.climb_const_vcas()['maximum']) /
                aero.kts)

            mach_const = kwargs.get(
                'mach_const_cl',
                np.random.uniform(self.wrap.climb_const_mach()['minimum'],
                                  self.wrap.climb_const_mach()['maximum']))

            h_cr = kwargs.get(
                'h_cr',
                np.random.uniform(self.wrap.cruise_alt()['minimum'],
                                  self.wrap.cruise_alt()['maximum']) * 1000)

            vs_pre_constcas = np.random.uniform(
                self.wrap.climb_vs_pre_concas()['minimum'],
                self.wrap.climb_vs_pre_concas()['maximum'])

            vs_constcas = np.random.uniform(
                self.wrap.climb_vs_concas()['minimum'],
                self.wrap.climb_vs_concas()['maximum'])

            vs_constmach = np.random.uniform(
                self.wrap.climb_vs_conmach()['minimum'],
                self.wrap.climb_vs_conmach()['maximum'])

        else:
            cas_const = kwargs.get(
                'cas_const_cl',
                self.wrap.climb_const_vcas()['default'] / aero.kts)
            mach_const = kwargs.get('mach_const_cl',
                                    self.wrap.climb_const_mach()['default'])
            h_cr = kwargs.get('h_cr', self.wrap.cruise_alt()['default'] * 1000)
            vs_pre_constcas = self.wrap.climb_vs_pre_concas()['default']
            vs_constcas = self.wrap.climb_vs_concas()['default']
            vs_constmach = self.wrap.climb_vs_conmach()['default']

        vcas_const = cas_const * aero.kts
        h_cr = np.round(h_cr / aero.ft,
                        -2) * aero.ft  # round cruise altitude to flight level
        vs_ic = self.wrap.initclimb_vs()['default']
        h_const_cas = self.wrap.climb_cross_alt_concas()['default'] * 1000

        h_const_mach = aero.crossover_alt(vcas_const, mach_const)
        if h_const_mach > h_cr:
            print(
                'Warining: const mach crossover altitude higher than cruise altitude, altitude clipped.'
            )

        data = []

        # intitial conditions
        t = 0
        tcr = 0
        h = 0
        s = 0
        v = 0
        vs = 0
        a = 0.5  # standard acceleration m/s^2
        seg = None

        while True:
            data.append([t, h, s, v, vs, seg])
            t = t + dt
            s = s + v * dt
            h = h + vs * dt

            if v < v_tof:
                v = v + a_tof * dt
                vs = 0
                seg = 'TO'
            elif h < 1500 * aero.ft:
                v = v + a * dt
                vs = vs_ic
                seg = 'IC'
            elif h < h_const_cas:
                v = v + a * dt
                if aero.tas2cas(v, h) >= vcas_const:
                    v = aero.cas2tas(vcas_const, h)
                vs = vs_pre_constcas
                seg = 'PRE-CAS'
            elif h < h_const_mach:
                v = aero.cas2tas(vcas_const, h)
                vs = vs_constcas
                seg = 'CAS'
            elif h < h_cr:
                v = aero.mach2tas(mach_const, h)
                vs = vs_constmach
                seg = 'MACH'
            else:
                v = aero.mach2tas(mach_const, h)
                vs = 0
                seg = 'CR'
                if tcr == 0:
                    tcr = t
                if t - tcr > 60:
                    break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            't': data[:, 0],
            'h': data[:, 1] + np.random.normal(0, self.sigma_h, ndata),
            's': data[:, 2] + np.random.normal(0, self.sigma_s, ndata),
            'v': data[:, 3] + np.random.normal(0, self.sigma_v, ndata),
            'vs': data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),
            'seg': data[:, 5],
            'cas_const_cl': cas_const,
            'mach_const_cl': mach_const,
            'h_cr': h_cr
        }

        return datadict

    def descent(self, **kwargs):
        """Generate descent trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_de (int): Constaant CAS for climb (kt).
            **mach_const_de (float): Constaant Mach for climb (-).
            **h_cr (int): Target cruise altitude (km).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: Flight trajectory.

        """
        dt = kwargs.get('dt', 1)
        random = kwargs.get('random', False)

        a_lnd = self.wrap.landing_acceleration()['default']
        v_app = self.wrap.finalapp_vcas()['default']

        if random:
            h_cr = kwargs.get(
                'h_cr',
                np.random.uniform(self.wrap.cruise_alt()['minimum'],
                                  self.wrap.cruise_alt()['maximum']) * 1000)

            mach_const = kwargs.get(
                'mach_const_de',
                np.random.uniform(self.wrap.descent_const_mach()['minimum'],
                                  self.wrap.descent_const_mach()['maximum']))

            cas_const = kwargs.get(
                'cas_const_de',
                np.random.uniform(self.wrap.descent_const_vcas()['minimum'],
                                  self.wrap.descent_const_vcas()['maximum']) /
                aero.kts)

            vs_constmach = np.random.uniform(
                self.wrap.descent_vs_conmach()['minimum'],
                self.wrap.descent_vs_conmach()['maximum'])

            vs_constcas = np.random.uniform(
                self.wrap.descent_vs_concas()['minimum'],
                self.wrap.descent_vs_concas()['maximum'])

            vs_post_constcas = np.random.uniform(
                self.wrap.descent_vs_post_concas()['minimum'],
                self.wrap.descent_vs_post_concas()['maximum'])

        else:
            mach_const = kwargs.get('mach_const_de',
                                    self.wrap.descent_const_mach()['default'])
            cas_const = kwargs.get(
                'cas_const_de',
                self.wrap.descent_const_vcas()['default'] / aero.kts)
            h_cr = kwargs.get('h_cr', self.wrap.cruise_alt()['default'] * 1000)
            vs_constmach = self.wrap.descent_vs_conmach()['default']
            vs_constcas = self.wrap.descent_vs_concas()['default']
            vs_post_constcas = self.wrap.descent_vs_post_concas()['default']

        vcas_const = cas_const * aero.kts
        h_cr = np.round(h_cr / aero.ft,
                        -2) * aero.ft  # round cruise altitude to flight level
        vs_fa = self.wrap.finalapp_vs()['default']
        h_const_cas = self.wrap.descent_cross_alt_concas()['default'] * 1000

        h_const_mach = aero.crossover_alt(vcas_const, mach_const)
        if h_const_mach > h_cr:
            print(
                'Warining: const mach crossover altitude higher than cruise altitude, altitude clipped.'
            )

        data = []

        # intitial conditions
        a = -0.5
        t = 0
        s = 0
        h = h_cr
        v = aero.mach2tas(mach_const, h_cr)
        vs = 0
        seg = None

        while True:
            data.append([t, h, s, v, vs, seg])
            t = t + dt
            s = s + v * dt
            h = h + vs * dt

            if t < 60:
                v = aero.mach2tas(mach_const, h)
                vs = 0
                seg = 'CR'
            elif h > h_const_mach:
                v = aero.mach2tas(mach_const, h)
                vs = vs_constmach
                seg = 'MACH'
            elif h > h_const_cas:
                v = aero.cas2tas(vcas_const, h)
                vs = vs_constcas
                seg = 'CAS'
            elif h > 1000 * aero.ft:
                v = v + a * dt
                if aero.tas2cas(v, h) < v_app:
                    v = aero.cas2tas(v_app, h)
                vs = vs_post_constcas
                seg = 'POST-CAS'
            elif h > 0:
                v = v_app
                vs = vs_fa
                seg = 'FA'
            else:
                h = 0
                vs = 0
                v = v + a_lnd * dt
                seg = 'LD'

                if v <= 0:
                    break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            't': data[:, 0],
            'h': data[:, 1] + np.random.normal(0, self.sigma_h, ndata),
            's': data[:, 2] + np.random.normal(0, self.sigma_s, ndata),
            'v': data[:, 3] + np.random.normal(0, self.sigma_v, ndata),
            'vs': data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),
            'seg': data[:, 5],
            'cas_const_de': cas_const,
            'vcas_const_de': vcas_const,
            'mach_const_de': mach_const,
            'h_cr': h_cr
        }

        return datadict

    def cruise(self, **kwargs):
        """Generate descent trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **range_cr (int): Cruise range (km).
            **h_cr (int): Cruise altitude (km).
            **mach_cr (float): Cruise Mach number (-).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: flight trajectory

        """
        dt = kwargs.get('dt', 1)
        random = kwargs.get('random', False)

        if random:
            range = kwargs.get(
                'range_cr',
                np.random.uniform(self.wrap.cruise_range()['minimum'],
                                  self.wrap.cruise_range()['maximum']) * 1000)

            h_cr = kwargs.get(
                'h_cr',
                np.random.uniform(self.wrap.cruise_alt()['minimum'],
                                  self.wrap.cruise_alt()['maximum']) * 1000)

            mach_cr = kwargs.get(
                'mach_cr',
                np.random.uniform(self.wrap.cruise_mach()['minimum'],
                                  self.wrap.cruise_mach()['maximum']))
        else:
            range = kwargs.get('range_cr',
                               self.wrap.cruise_range()['default'] * 1000)
            mach_cr = kwargs.get('mach_cr', self.wrap.cruise_mach()['default'])
            h_cr = kwargs.get('h_cr', self.wrap.cruise_alt()['default'] * 1000)

        h_cr = np.round(h_cr / aero.ft,
                        -3) * aero.ft  # round cruise altitude to flight level

        data = []

        # intitial conditions
        t = 0
        s = 0
        v = aero.mach2tas(mach_cr, h_cr)
        vs = 0

        while True:
            data.append([t, h_cr, s, v, vs])
            t = t + dt
            s = s + v * dt

            if s > range:
                break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            't': data[:, 0],
            'h': data[:, 1] + np.random.normal(0, self.sigma_h, ndata),
            's': data[:, 2] + np.random.normal(0, self.sigma_s, ndata),
            'v': data[:, 3] + np.random.normal(0, self.sigma_v, ndata),
            'vs': data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),
            'h_cr': h_cr,
            'mach_cr': mach_cr,
        }

        return datadict

    def complete(self, **kwargs):
        """Generate a complete trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_cl (int): Constaant CAS for climb (kt).
            **mach_const_cl (float): Constaant Mach for climb (-).
            **cas_const_de (int): Constaant CAS for climb (kt).
            **mach_const_de (float): Constaant Mach for climb (-).
            **range_cr (int): Cruise range (km).
            **h_cr (int): Target cruise altitude (km).
            **mach_cr (float): Cruise Mach number (-).
            **random (bool): Generate trajectory with random paramerters.
        Returns:
            dict: Flight trajectory.

        """
        data_cr = self.cruise(**kwargs)
        data_cl = self.climb(h_cr=data_cr['h_cr'],
                             mach_cr=data_cr['mach_cr'],
                             **kwargs)
        data_de = self.descent(h_cr=data_cr['h_cr'],
                               mach_cr=data_cr['mach_cr'],
                               **kwargs)

        data = {
            't':
            np.concatenate([
                data_cl['t'], data_cl['t'][-1] + data_cr['t'],
                data_cl['t'][-1] + data_cr['t'][-1] + data_de['t']
            ]),
            'h':
            np.concatenate([data_cl['h'], data_cr['h'], data_de['h']]),
            's':
            np.concatenate([
                data_cl['s'], data_cl['s'][-1] + data_cr['s'],
                data_cl['s'][-1] + data_cr['s'][-1] + data_de['s']
            ]),
            'v':
            np.concatenate([data_cl['v'], data_cr['v'], data_de['v']]),
            'vs':
            np.concatenate([data_cl['vs'], data_cr['vs'], data_de['vs']]),
        }
        return data
示例#6
0
文件: gen.py 项目: sthagen/openap
class Generator(object):
    """Generate trajectory using WRAP model."""
    def __init__(self, ac, eng=None):
        """Intitialize the generator.

        Args:
            ac (string): Aircraft type.
            eng (string): Engine type. Leave empty for default engine type in OpenAP.

        Returns:
            dict: flight trajectory

        """
        super(Generator, self).__init__()

        self.ac = ac
        self.acdict = prop.aircraft(self.ac)

        if eng is None:
            self.eng = self.acdict["engine"]["default"]
        else:
            self.eng = eng
        self.engdict = prop.engine(self.eng)

        self.wrap = WRAP(self.ac)
        # self.thrust = Thrust(self.ac, self.eng)
        # self.drag = Drag(self.ac)
        # self.fuelflow = Thrust(self.ac, self.eng)

        # for noise generation
        self.sigma_v = 0
        self.sigma_vs = 0
        self.sigma_h = 0
        self.sigma_s = 0

    def enable_noise(self):
        """Adding noise to the generated trajectory.

        The noise model is based on ADS-B Version 1&2, NACv=3 and NACp=10
        """
        self.sigma_v = 0.5
        self.sigma_vs = 0.75
        self.sigma_h = 7.5
        self.sigma_s = 5

    def climb(self, **kwargs):
        """Generate climb trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_cl (int): Constaant CAS for climb (kt).
            **mach_const_cl (float): Constaant Mach for climb (-).
            **alt_cr (int): Target cruise altitude (ft).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: Flight trajectory.

        """
        dt = kwargs.get("dt", 1)
        random = kwargs.get("random", False)

        a_tof = self.wrap.takeoff_acceleration()["default"]
        v_tof = self.wrap.takeoff_speed()["default"]

        if random:
            cas_const = kwargs.get(
                "cas_const_cl",
                np.random.uniform(
                    self.wrap.climb_const_vcas()["minimum"],
                    self.wrap.climb_const_vcas()["maximum"],
                ) / aero.kts,
            )

            mach_const = kwargs.get(
                "mach_const_cl",
                np.random.uniform(
                    self.wrap.climb_const_mach()["minimum"],
                    self.wrap.climb_const_mach()["maximum"],
                ),
            )

            alt_cr = kwargs.get(
                "alt_cr",
                np.random.uniform(self.wrap.cruise_alt()["minimum"],
                                  self.wrap.cruise_alt()["maximum"]) * 1000 /
                aero.ft,
            )

            vs_pre_constcas = np.random.uniform(
                self.wrap.climb_vs_pre_concas()["minimum"],
                self.wrap.climb_vs_pre_concas()["maximum"],
            )

            vs_constcas = np.random.uniform(
                self.wrap.climb_vs_concas()["minimum"],
                self.wrap.climb_vs_concas()["maximum"],
            )

            vs_constmach = np.random.uniform(
                self.wrap.climb_vs_conmach()["minimum"],
                self.wrap.climb_vs_conmach()["maximum"],
            )

        else:
            cas_const = kwargs.get(
                "cas_const_cl",
                self.wrap.climb_const_vcas()["default"] / aero.kts)
            cas_const = max(
                cas_const,
                v_tof / aero.kts)  # cas can not be smaller then takeoff speed
            mach_const = kwargs.get("mach_const_cl",
                                    self.wrap.climb_const_mach()["default"])
            alt_cr = kwargs.get(
                "alt_cr",
                self.wrap.cruise_alt()["default"] * 1000 / aero.ft)
            vs_pre_constcas = self.wrap.climb_vs_pre_concas()["default"]
            vs_constcas = self.wrap.climb_vs_concas()["default"]
            vs_constmach = self.wrap.climb_vs_conmach()["default"]

        vcas_const = cas_const * aero.kts
        alt_cr = np.round(alt_cr, -2)  # round cruise altitude to flight level
        h_cr = alt_cr * aero.ft  # meters
        vs_ic = self.wrap.initclimb_vs()["default"]
        h_const_cas = self.wrap.climb_cross_alt_concas()["default"] * 1000

        h_const_mach = aero.crossover_alt(vcas_const, mach_const)
        if h_const_mach > h_cr:
            print(
                "Warining: const mach crossover altitude higher than cruise altitude, altitude clipped."
            )

        data = []

        # intitial conditions
        t = 0
        tcr = 0
        h = 0
        s = 0
        v = 0
        vs = 0
        a = 0.5  # standard acceleration m/s^2
        seg = None

        while True:
            data.append([t, h, s, v, vs, seg])
            t = t + dt
            s = s + v * dt
            h = h + vs * dt

            if v < v_tof:
                v = v + a_tof * dt
                vs = 0
                seg = "TO"
            elif h < 1500 * aero.ft:
                v = v + a * dt
                if aero.tas2cas(v, h) >= vcas_const:
                    v = aero.cas2tas(vcas_const, h)
                vs = vs_ic
                seg = "IC"
            elif h < h_const_cas:
                v = v + a * dt
                if aero.tas2cas(v, h) >= vcas_const:
                    v = aero.cas2tas(vcas_const, h)
                vs = vs_pre_constcas
                seg = "PRE-CAS"
            elif h < h_const_mach:
                v = aero.cas2tas(vcas_const, h)
                vs = vs_constcas
                seg = "CAS"
            elif h < h_cr:
                v = aero.mach2tas(mach_const, h)
                vs = vs_constmach
                seg = "MACH"
            else:
                v = aero.mach2tas(mach_const, h)
                vs = 0
                seg = "CR"
                if tcr == 0:
                    tcr = t
                if t - tcr > 60:
                    break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            "t": data[:, 0],  # t, seconds
            "h": data[:, 1] + np.random.normal(0, self.sigma_h, ndata),  # h, m
            "s": data[:, 2] + np.random.normal(0, self.sigma_s, ndata),  # s, m
            "v":
            data[:, 3] + np.random.normal(0, self.sigma_v, ndata),  # v, m/s
            "vs":
            data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),  # VS, m/s
            "seg": data[:, 5],
            "cas_const_cl": cas_const,
            "mach_const_cl": mach_const,
            "alt_cr": alt_cr,  # alt_cr, ft
        }

        return datadict

    def descent(self, **kwargs):
        """Generate descent trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_de (int): Constaant CAS for climb (kt).
            **mach_const_de (float): Constaant Mach for climb (-).
            **alt_cr (int): Target cruise altitude (ft).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: Flight trajectory.

        """
        dt = kwargs.get("dt", 1)
        random = kwargs.get("random", False)

        a_lnd = self.wrap.landing_acceleration()["default"]
        v_app = self.wrap.finalapp_vcas()["default"]

        if random:
            alt_cr = kwargs.get(
                "alt_cr",
                np.random.uniform(self.wrap.cruise_alt()["minimum"],
                                  self.wrap.cruise_alt()["maximum"]) * 1000 /
                aero.ft,
            )

            mach_const = kwargs.get(
                "mach_const_de",
                np.random.uniform(
                    self.wrap.descent_const_mach()["minimum"],
                    self.wrap.descent_const_mach()["maximum"],
                ),
            )

            cas_const = kwargs.get(
                "cas_const_de",
                np.random.uniform(
                    self.wrap.descent_const_vcas()["minimum"],
                    self.wrap.descent_const_vcas()["maximum"],
                ) / aero.kts,
            )

            vs_constmach = np.random.uniform(
                self.wrap.descent_vs_conmach()["minimum"],
                self.wrap.descent_vs_conmach()["maximum"],
            )

            vs_constcas = np.random.uniform(
                self.wrap.descent_vs_concas()["minimum"],
                self.wrap.descent_vs_concas()["maximum"],
            )

            vs_post_constcas = np.random.uniform(
                self.wrap.descent_vs_post_concas()["minimum"],
                self.wrap.descent_vs_post_concas()["maximum"],
            )

        else:
            mach_const = kwargs.get("mach_const_de",
                                    self.wrap.descent_const_mach()["default"])
            cas_const = kwargs.get(
                "cas_const_de",
                self.wrap.descent_const_vcas()["default"] / aero.kts)
            alt_cr = kwargs.get(
                "alt_cr",
                self.wrap.cruise_alt()["default"] * 1000 / aero.ft)
            vs_constmach = self.wrap.descent_vs_conmach()["default"]
            vs_constcas = self.wrap.descent_vs_concas()["default"]
            vs_post_constcas = self.wrap.descent_vs_post_concas()["default"]

        vcas_const = cas_const * aero.kts
        alt_cr = np.round(alt_cr, -2)  # round cruise altitude to flight level
        h_cr = alt_cr * aero.ft
        vs_fa = self.wrap.finalapp_vs()["default"]
        h_const_cas = self.wrap.descent_cross_alt_concas()["default"] * 1000

        h_const_mach = aero.crossover_alt(vcas_const, mach_const)
        if h_const_mach > h_cr:
            print(
                "Warining: const mach crossover altitude higher than cruise altitude, altitude clipped."
            )

        data = []

        # intitial conditions
        a = -0.5
        t = 0
        s = 0
        h = h_cr
        v = aero.mach2tas(mach_const, h_cr)
        vs = 0
        seg = None

        while True:
            data.append([t, h, s, v, vs, seg])
            t = t + dt
            s = s + v * dt
            h = h + vs * dt

            if t < 60:
                v = aero.mach2tas(mach_const, h)
                vs = 0
                seg = "CR"
            elif h > h_const_mach:
                v = aero.mach2tas(mach_const, h)
                vs = vs_constmach
                seg = "MACH"
            elif h > h_const_cas:
                v = aero.cas2tas(vcas_const, h)
                vs = vs_constcas
                seg = "CAS"
            elif h > 1000 * aero.ft:
                v = v + a * dt
                if aero.tas2cas(v, h) < v_app:
                    v = aero.cas2tas(v_app, h)
                vs = vs_post_constcas
                seg = "POST-CAS"
            elif h > 0:
                v = v_app
                vs = vs_fa
                seg = "FA"
            else:
                h = 0
                vs = 0
                v = v + a_lnd * dt
                seg = "LD"

                if v <= 0:
                    break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            "t": data[:, 0],
            "h": data[:, 1] + np.random.normal(0, self.sigma_h, ndata),
            "s": data[:, 2] + np.random.normal(0, self.sigma_s, ndata),
            "v": data[:, 3] + np.random.normal(0, self.sigma_v, ndata),
            "vs": data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),
            "seg": data[:, 5],
            "cas_const_de": cas_const,
            "vcas_const_de": vcas_const,
            "mach_const_de": mach_const,
            "alt_cr": alt_cr,
        }

        return datadict

    def cruise(self, **kwargs):
        """Generate descent trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **range_cr (int): Cruise range (km).
            **alt_cr (int): Cruise altitude (ft).
            **mach_cr (float): Cruise Mach number (-).
            **random (bool): Generate trajectory with random paramerters.

        Returns:
            dict: flight trajectory

        """
        dt = kwargs.get("dt", 1)
        random = kwargs.get("random", False)

        if random:
            range = kwargs.get(
                "range_cr",
                np.random.uniform(
                    self.wrap.cruise_range()["minimum"],
                    self.wrap.cruise_range()["maximum"],
                ) * 1000,
            )

            alt_cr = kwargs.get(
                "alt_cr",
                np.random.uniform(self.wrap.cruise_alt()["minimum"],
                                  self.wrap.cruise_alt()["maximum"]) * 1000 /
                aero.ft,
            )

            mach_cr = kwargs.get(
                "mach_cr",
                np.random.uniform(
                    self.wrap.cruise_mach()["minimum"],
                    self.wrap.cruise_mach()["maximum"],
                ),
            )
        else:
            range = kwargs.get("range_cr",
                               self.wrap.cruise_range()["default"] * 1000)
            mach_cr = kwargs.get("mach_cr", self.wrap.cruise_mach()["default"])
            alt_cr = kwargs.get(
                "alt_cr",
                self.wrap.cruise_alt()["default"] * 1000 / aero.ft)

        alt_cr = np.round(alt_cr, -2)  # round cruise altitude to flight level
        h_cr = alt_cr * aero.ft

        data = []

        # intitial conditions
        t = 0
        s = 0
        v = aero.mach2tas(mach_cr, h_cr)
        vs = 0

        while True:
            data.append([t, h_cr, s, v, vs])
            t = t + dt
            s = s + v * dt

            if s > range:
                break

        data = np.array(data)
        ndata = len(data)
        datadict = {
            "t": data[:, 0],
            "h": data[:, 1] + np.random.normal(0, self.sigma_h, ndata),
            "s": data[:, 2] + np.random.normal(0, self.sigma_s, ndata),
            "v": data[:, 3] + np.random.normal(0, self.sigma_v, ndata),
            "vs": data[:, 4] + np.random.normal(0, self.sigma_vs, ndata),
            "alt_cr": alt_cr,
            "mach_cr": mach_cr,
        }

        return datadict

    def complete(self, **kwargs):
        """Generate a complete trajectory based on WRAP model.

        Args:
            **dt (int): Time step in seconds.
            **cas_const_cl (int): Constaant CAS for climb (kt).
            **mach_const_cl (float): Constaant Mach for climb (-).
            **cas_const_de (int): Constaant CAS for climb (kt).
            **mach_const_de (float): Constaant Mach for climb (-).
            **range_cr (int): Cruise range (km).
            **alt_cr (int): Target cruise altitude (ft).
            **mach_cr (float): Cruise Mach number (-).
            **random (bool): Generate trajectory with random paramerters.
        Returns:
            dict: Flight trajectory.

        """
        data_cr = self.cruise(**kwargs)

        if "alt_cr" not in kwargs:
            kwargs["alt_cr"] = data_cr["alt_cr"]

        data_cl = self.climb(mach_const_cl=data_cr["mach_cr"], **kwargs)

        data_de = self.descent(mach_const_de=data_cr["mach_cr"], **kwargs)

        data = {
            "t":
            np.concatenate([
                data_cl["t"],
                data_cl["t"][-1] + data_cr["t"],
                data_cl["t"][-1] + data_cr["t"][-1] + data_de["t"],
            ]),
            "h":
            np.concatenate([data_cl["h"], data_cr["h"], data_de["h"]]),
            "s":
            np.concatenate([
                data_cl["s"],
                data_cl["s"][-1] + data_cr["s"],
                data_cl["s"][-1] + data_cr["s"][-1] + data_de["s"],
            ]),
            "v":
            np.concatenate([data_cl["v"], data_cr["v"], data_de["v"]]),
            "vs":
            np.concatenate([data_cl["vs"], data_cr["vs"], data_de["vs"]]),
        }
        return data
示例#7
0
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:], [], [])
示例#8
0
from openap import prop, FuelFlow, Emission, WRAP

available_acs = prop.available_aircraft(use_synonym=True)

for actype in available_acs:
    # print(actype)
    aircraft = prop.aircraft(ac=actype, use_synonym=True)
    wrap = WRAP(ac=actype, use_synonym=True)
    fuelflow = FuelFlow(ac=actype, use_synonym=True)
    emission = Emission(ac=actype, use_synonym=True)


available_acs = prop.available_aircraft(use_synonym=False)

for actype in available_acs:
    # print(actype)
    aircraft = prop.aircraft(ac=actype, use_synonym=False)
    wrap = WRAP(ac=actype, use_synonym=True)
    fuelflow = FuelFlow(ac=actype, use_synonym=True)
    emission = Emission(ac=actype, use_synonym=True)
示例#9
0
from openap import WRAP

wrap = WRAP('A320')

for func in dir(wrap):
    if callable(getattr(wrap, func)):
        if not func.startswith('_'):
            print(getattr(wrap, func)())