Ejemplo n.º 1
0
def long_modes(aircraft, x_0, u_0):
    """longitudinal mode calculations."""
    j = aircraft['weight']['inertia']
    m = aircraft['weight']['weight'] / g  # [slug]
    x_ss = [0, 2, 4, 7]
    a, b, c, d = nonlinear_eom_to_ss(aircraft, x_ss, [1], x_0, u_0, m, j)
    sys = StateSpace(a, b, c, d)
    wn, zeta, poles = damp(sys)
    wn_sp = unique(max(wn))
    zeta_sp = unique(zeta[wn == wn_sp])
    wn_ph = unique(min(wn))
    zeta_ph = unique(zeta[wn == wn_ph])
    return wn_sp, zeta_sp, wn_ph, zeta_ph
Ejemplo n.º 2
0
def latdir_modes(aircraft, x_0, u_0):
    """calculate lateral-directional modal parameters."""
    j = aircraft['weight']['inertia']
    m = aircraft['weight']['weight'] / g  # slug
    # x = [u v w phi theta psi p q r p_n p_e h]
    x_ss = [1, 3, 6, 8]
    a, b, c, d = nonlinear_eom_to_ss(aircraft, x_ss, [0, 2], x_0, u_0, m, j)
    sys = StateSpace(a, b, c, d)
    wn, zeta, poles = damp(sys)
    wn_dr = unique(max(wn[abs(zeta) != 1]))  # [rad/s]
    zeta_dr = unique(max(zeta[wn == wn_dr]))  # []
    re = real(poles)
    t = unique(re[abs(zeta) == 1])
    if len(t) == 2:
        t_r = -1 / min(t)
        t_s = -1 / max(t)
    else:
        t_r = float("nan")
        t_s = float("nan")
    return wn_dr, zeta_dr, t_r, t_s
Ejemplo n.º 3
0
def step_info(sysc):

    wn, damping, poles = ct.damp(sysc, doprint=False)
    z = damping[0]
    wn = wn[0]
    wd = wn * m.sqrt(1 - (z)**2)
    theta = m.atan(m.sqrt(1 - (z)**2) / (z))

    tr = (m.pi - theta) / wd
    print('RiseTime:', format(tr, '.4f'))

    ts = 4 / ((z) * (wn))
    print('SettlingTime:', format(ts, '.4f'))

    Mp = (m.exp(-z * m.pi / m.sqrt(1 - (z)**2))) * 100
    print('Overshoot:', format(Mp, '.4f'), '%')

    tp = m.pi / wd
    print('PeakTime:', format(tp, '.4f'))
    print('')
    print('')

    return
Ejemplo n.º 4
0
u = np.array([dutch[4], dutch[5]])

#Calculate response to arbitrary input
t, y, x = control.forced_response(system,
                                  dutch[0],
                                  u,
                                  dutch[6],
                                  transpose=False)

#Change dimensionless pb/(2V) and rb/(2V) to p and r
y[1, :] = -y[1, :] + 2 * y[1, 0]
y[2, :] = -(2 * abs(V0) * y[2, :] / b) + 2 * y[2, 0]
y[3, :] = -(2 * abs(V0) * y[3, :] / b) + 2 * y[3, 0]

control.damp(system, doprint=True)

fig = plt.figure(figsize=(12, 9))
fig.suptitle('Dutch Roll', fontsize=16)

ax1 = fig.add_subplot(221)
ax1.plot(t, y[0, :], label='Simulated response')
ax1.plot(t,
         dutch[8],
         label='Test Flight Data Response',
         color='tab:orange',
         linestyle='--')
ax1.legend()
ax1.set_xlabel("Time [s]")
ax1.set_ylabel("beta (yaw angle) [deg]")
ax1.grid()
Ejemplo n.º 5
0
#---------------------------------------------------------

#---------------------Phugoid------------------------------

#Short, sharp deflection followed by a return to the centered position

#xinit = np.array([Vtrue[25360]*np.cos(vane_AOA[25360]*(np.pi/180)), vane_AOA[25360]*(np.pi/180), pitch[25360]*(np.pi/180), pitch_rate[25360]*(np.pi/180)])
xinit = np.array([0,0,0,0])
Udeltae = deltae[25360:26910]*(np.pi/180)

#Generating an output vector with velocity

C = np.array([[1,0,0,0]])
D = np.array([[0]])
sys = ctrl.ss(A_sym,B_sym,C,D)
ctrl.damp(sys)

T, u_sim, xout = ctrl.forced_response(sys, T=np.arange(0,155,0.1), U=Udeltae.T,  X0=xinit)
u_sim = u_sim + Vtrue[25360]*np.cos(vane_AOA[25360]*(np.pi/180))            #For the initial condition

#Generating an output vector with angle of attack

C = np.array([[0,1,0,0]])
D = np.array([[0]])

sys = ctrl.ss(A_sym,B_sym,C,D)

T, aoa_sim, xout = ctrl.forced_response(sys, T=np.arange(0,155,0.1), U=Udeltae.T, X0=xinit)
aoa_sim = aoa_sim + vane_AOA[25360]*(np.pi/180)                             #For the initial condition

#Generating an output vector with pitch angle
Ejemplo n.º 6
0
import matplotlib.pyplot as plt
from scipy import signal
from matplotlib.ticker import (MultipleLocator)

Gp = ct.tf(100, [1, 0, 100])
ts = 0.05
Gz = ct.sample_system(Gp, ts)
sym.pprint(Gz)
t = np.arange(0.0, 50 * ts, ts)
(num, den) = ct.tfdata(Gp)  ## por que GP???? lsim no funciona con Gz
num = np.array(num)  ##np.asarray hace lo mismo convierte tuple/list a array
den = np.array(den)
num = num.flatten()
den = den.flatten()

do = ct.damp(
    Gz, doprint=True
)  ##damp me devuelve en vez de un vector, un tuple (parecido a una matriz) que contiene todos los datos
sys = signal.lti(
    num, den)  ##transformo Gp en lti que es lo que acepta la syntax de lsim
wn = do[
    0]  ## 0 contiene wn, 1 contiene damping, 2 contiene eigen de los dos polos

x = np.sin(wn[0] * t)  ##escojo el valor de wn de un polo

fig, ax = plt.subplots()

tout, a, b = signal.lsim(sys, x, t)
plt.plot(t, x)
plt.step(t, a)
plt.show()
Ejemplo n.º 7
0
t_function = con.tf(num, den)

#linear simulation  we can see a response to input of system
#we need u(t)= input of system and x(t) inicial condition
# u =! 0 and x == 0 homogeny solucion # u == 0 and x =! 0 forced solution
# u =! 0 and x =! 0 full solution

#plot response

sys_state = con.ss(a, b, c, d)
time_simulation = np.arange(0, 30, 0.01, dtype=float)  #time start 0
input_u = 2 * np.ones(np.size(time_simulation))  #input of 2 volts
start_condition = np.array([[1], [0]])
t, y_out, x_out = con.forced_response(sys_state, time_simulation, input_u,
                                      start_condition)
[wn, zetas, poles] = con.damp(sys_state)
#t,y_out, = con.initial_response(sys_state,time_simulation,start_condition)

[time2, yout2] = con.step_response(t_function, time_simulation,
                                   start_condition)
plt.figure(1)
plt.plot(time2, yout2, 'r')
plt.xlabel('time')
plt.ylabel('volts')

plt.figure(2)
plt.plot(t, y_out, 'b*', t, input_u,
         'g-')  #ploting time x output and time x input
plt.xlabel('time')
plt.ylabel('volts')
plt.show()
    def compute_assymetric_ss_representation_error(self, stability_coeffs_array):
        """

        :param stability_coeffs_array: [Cnb, Cnr, CYb]
        :return:
        """
        forced_response_inputs = self.maneuver_vals()
        # spiral = maneuver_vals(3305, 30, 'Spiral')
        # aperiodic = maneuver_vals(3380, 30, 'Aperiodic')

        g = 9.80665
        # State-space representation of asymmetric EOM:
        V0 = forced_response_inputs[7]

        mub, muc, m, h, rho = self.get_flight_conditions()
        mub = float(mub[0])
        muc = float(muc[0])
        m = float(m[0])
        h = float(h[0])
        rho = float(rho[0])

        CX0 = m * g * sin(forced_response_inputs[3][0] * np.pi / 180.0) / (0.5 * rho * (V0 ** 2) * S)
        CZ0 = -m * g * cos(forced_response_inputs[3][0] * np.pi / 180.0) / (0.5 * rho * (V0 ** 2) * S)

        c = 2.0569

        C1 = np.array([[(CYbdot - 2.0 * mub) * b / V0, 0.0, 0.0, 0.0],
                       [0.0, -0.5 * b / V0, 0.0, 0.0],
                       [0.0, 0.0, -4.0 * mub * KX2 * b / V0, 4.0 * mub * KXZ * b / V0],
                       [Cnbdot * b / V0, 0.0, 4.0 * mub * KXZ * b / V0, -4.0 * mub * KZ2 * b / V0]])

        C2 = np.array([[-stability_coeffs_array[2], -CL, -CYp, -(CYr - 4.0 * mub)],
                       [0.0, 0.0, -1.0, 0.0],
                       [-Clb, 0.0, -Clp, -Clr],
                       [-stability_coeffs_array[0], 0.0, -Cnp, -stability_coeffs_array[1]]])

        C3 = np.array([[-CYda, -CYdr],
                       [0.0, 0.0],
                       [-Clda, -Cldr],
                       [-Cnda, -Cndr]])

        A = np.matmul(np.linalg.inv(C1), C2)
        B = np.matmul(np.linalg.inv(C1), C3)
        C = np.identity(4)  # y = x, meaning we output the state
        D = np.array([[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])

        # Make control.ss state-space

        system = control.ss(A, B, C, D)

        # t = np.linspace(0.0, 200.0, num = 201)

        # Input:
        # u = np.zeros((2, t.shape[0]))

        # for i in range(t.shape[0]):
        #    u[0, i] = da[i] #Insert magnitude of "da" (aileron deflection) or comment out if none
        #    u[1, i] = dr[i] #Insert magnitude of "dr" (rudder deflection) or comment out if none

        u = np.array([forced_response_inputs[4],
                      forced_response_inputs[5]])

        # Calculate response to arbitrary input
        t, y, x = control.forced_response(system, forced_response_inputs[0], u, forced_response_inputs[6], transpose=False)

        # Change dimensionless pb/(2V) and rb/(2V) to p and r
        y[1, :] = -y[1, :] + 2 * y[1, 0]
        y[2, :] = -(2 * abs(V0) * y[2, :] / b) + 2 * y[2, 0]
        y[3, :] = -(2 * abs(V0) * y[3, :] / b) + 2 * y[3, 0]

        control.damp(system, doprint=True)

        eigen_motion_error_beta = self.L2error(forced_response_inputs[8], y[0, :])
        eigen_motion_error_phi = self.L2error(forced_response_inputs[1], y[1, :])
        eigen_motion_error_p = self.L2error(forced_response_inputs[2], y[2, :])
        eigen_motion_error_r = self.L2error(forced_response_inputs[3], y[3, :])
        avg_eigen_motion_error = (eigen_motion_error_beta + eigen_motion_error_p + eigen_motion_error_phi + eigen_motion_error_r) / 4.0

        print("The Average Error Computed for the {0} is: {1}".format(self.maneuver_name, avg_eigen_motion_error))
        return avg_eigen_motion_error
    def create_assymetric_ss_representation(self):
        forced_response_inputs = self.maneuver_vals()

        g = 9.80665

        # DUTCH ROLL:
        # State-space representation of asymmetric EOM:

        # C1*x' + C2*x + C3*u = 0

        V0 = forced_response_inputs[7]

        mub, muc, m, h, rho = self.get_flight_conditions()
        mub = float(mub[0])
        muc = float(muc[0])
        m = float(m[0])
        h = float(h[0])
        rho = float(rho[0])

        CX0 = m * g * sin(forced_response_inputs[3][0] * np.pi / 180.0) / (0.5 * rho * (V0 ** 2) * S)
        CZ0 = -m * g * cos(forced_response_inputs[3][0] * np.pi / 180.0) / (0.5 * rho * (V0 ** 2) * S)

        c = 2.0569

        C1 = np.array([[(CYbdot - 2.0 * mub) * b / V0, 0.0, 0.0, 0.0],
                       [0.0, -0.5 * b / V0, 0.0, 0.0],
                       [0.0, 0.0, -4.0 * mub * KX2 * b / V0, 4.0 * mub * KXZ * b / V0],
                       [Cnbdot * b / V0, 0.0, 4.0 * mub * KXZ * b / V0, -4.0 * mub * KZ2 * b / V0]])

        C2 = np.array([[-CYb, -CL, -CYp, -(CYr - 4.0 * mub)],
                       [0.0, 0.0, -1.0, 0.0],
                       [-Clb, 0.0, -Clp, -Clr],
                       [-Cnb, 0.0, -Cnp, -Cnr]])

        C3 = np.array([[-CYda, -CYdr],
                       [0.0, 0.0],
                       [-Clda, -Cldr],
                       [-Cnda, -Cndr]])

        # x' = A*x + B*u
        # y  = C*x + D*u

        # now u = [da]
        #         [dr]

        A = np.matmul(np.linalg.inv(C1), C2)
        B = np.matmul(np.linalg.inv(C1), C3)
        C = np.identity(4)  # y = x, meaning we output the state
        D = np.array([[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]])

        # Make control.ss state-space

        system = control.ss(A, B, C, D)

        # t = np.linspace(0.0, 200.0, num = 201)

        # Input:
        # u = np.zeros((2, t.shape[0]))

        # for i in range(t.shape[0]):
        #    u[0, i] = da[i] #Insert magnitude of "da" (aileron deflection) or comment out if none
        #    u[1, i] = dr[i] #Insert magnitude of "dr" (rudder deflection) or comment out if none

        u = np.array([forced_response_inputs[4],
                      forced_response_inputs[5]])

        # Calculate response to arbitrary input
        t, y, x = control.forced_response(system, forced_response_inputs[0], u, forced_response_inputs[6], transpose=False)

        # Change dimensionless pb/(2V) and rb/(2V) to p and r
        y[1, :] = -y[1, :] + 2 * y[1, 0]
        y[2, :] = -(2 * abs(V0) * y[2, :] / b) + 2 * y[2, 0]
        y[3, :] = -(2 * abs(V0) * y[3, :] / b) + 2 * y[3, 0]

        control.damp(system, doprint=True)

        fig = plt.figure(figsize=(12, 9))
        # fig.suptitle(self.maneuver_name, fontsize=16, )

        ax1 = fig.add_subplot(221)
        ax1.plot(t, y[0, :], label='Simulated response')
        ax1.plot(t, forced_response_inputs[8], label='Test Flight Data Response', color='tab:orange', linestyle='--')
        ax1.legend(loc='upper right')
        ax1.set_xlabel("Time [s]")
        ax1.set_ylabel("beta (yaw angle) [deg]")
        print("{0} Error in Beta:".format(self.maneuver_name))
        eigen_motion_error_beta = self.L2error(forced_response_inputs[8], y[0, :])
        print(eigen_motion_error_beta)
        plt.grid("True")

        ax2 = fig.add_subplot(222)
        ax2.plot(t, y[1, :], label='Simulated response')
        ax2.plot(t, forced_response_inputs[1], label='Test Flight Data Response', color='tab:orange', linestyle='--')
        ax2.legend(loc='upper right')
        ax2.set_xlabel("Time [s]")
        ax2.set_ylabel("phi (roll angle) [deg]")
        print("{0} Error in Phi:".format(self.maneuver_name))
        eigen_motion_error_phi = self.L2error(forced_response_inputs[1], y[1, :])
        print(eigen_motion_error_phi)
        plt.grid("True")

        ax3 = fig.add_subplot(223)
        ax3.plot(t, y[2, :], label='Simulated response')
        ax3.plot(t, forced_response_inputs[2], label='Test Flight Data Response', color='tab:orange', linestyle='--')
        ax3.legend(loc='upper right')
        ax3.set_xlabel("Time [s]")
        ax3.set_ylabel("p (roll rate) [deg/sec]")
        print("{0} Error in p:".format(self.maneuver_name))
        eigen_motion_error_p = self.L2error(forced_response_inputs[2], y[2, :])
        print(eigen_motion_error_p)
        plt.grid("True")

        ax4 = fig.add_subplot(224)
        ax4.plot(t, y[3, :], label='Simulated response')
        ax4.plot(t, forced_response_inputs[3], label='Test Flight Data Response', color='tab:orange', linestyle='--')
        ax4.legend(loc='upper right')
        ax4.set_xlabel("Time [s]")
        ax4.set_ylabel("r (yaw rate) [deg/s]")
        print("{0} Error in r:".format(self.maneuver_name))
        eigen_motion_error_r = self.L2error(forced_response_inputs[3], y[3, :])
        print(eigen_motion_error_r)
        plt.grid("True")

        print("Avg. {0} Error:".format(self.maneuver_name))
        avg_eigen_motion_error = (eigen_motion_error_beta + eigen_motion_error_p + eigen_motion_error_phi + eigen_motion_error_r) / 4.0
        print(avg_eigen_motion_error)
        # plt.grid("True")
        plt.show()