def func_fuel(self, x, mass): mach, h = denormalize(x, self.normfactor) va = aero.mach2tas(mach, h) ff = self.fuelflow.enroute(mass, va / aero.kts, h / aero.ft) ff_m = ff / (va + 1e-3) * 1000 # print("%.03f" % mach, "%d" % (h/aero.ft), "%.05f" % ff_m) return ff_m
def func_cons_thrust(self, x, mass): mach, h = denormalize(x, self.normfactor) va = aero.mach2tas(mach, h) D = self.drag.clean(mass, va / aero.kts, h / aero.ft) Tmax = self.thrust.cruise(va / aero.kts, h / aero.ft) dT = Tmax - D return dT
def func_cons_lift(self, x, mass): mach, h = denormalize(x, self.normfactor) va = aero.mach2tas(mach, h) Tmax = self.thrust.cruise(va / aero.kts, h / aero.ft) qS = 0.5 * aero.density(h) * va**2 * self.aircraft['wing']['area'] cd0 = self.drag.polar['clean']['cd0'] k = self.drag.polar['clean']['k'] mach_crit = self.drag.polar['mach_crit'] if mach > mach_crit: cd0 += 20 * (mach - mach_crit)**4 dL2 = qS**2 * (1 / k * (Tmax / (qS + 1e-3) - cd0)) - (mass * aero.g0)**2 return dL2
def func_time(self, x, mass): mach, h = denormalize(x, self.normfactor) va = aero.mach2tas(mach, h) va_inv = 1 / (va + 1e-4) * 1000 # print("%.03f" % mach, "%d" % (h/aero.ft), "%.02f" % va) return va_inv
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 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 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 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 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 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