예제 #1
0
def dT_d_x_q(e):
    eps = .01
    dtheta_de = np.zeros((3, 4))
    phi_at_e, theta_at_e, psi_at_e = Quaternion2Euler(e)
    for i in range(0, 4):
        e_eps = np.copy(e)
        e_eps[i][0] += eps  # add eps to the ith state
        normE = np.sqrt(e_eps[0][0]**2 + e_eps[1][0]**2 + e_eps[2][0]**2 +
                        e_eps[3][0]**2)
        e_eps[0][0] = e_eps[0][0] / normE
        e_eps[1][0] = e_eps[1][0] / normE
        e_eps[2][0] = e_eps[2][0] / normE
        e_eps[3][0] = e_eps[3][0] / normE
        phi_at_e_eps, theta_at_e_eps, psi_at_e_eps = Quaternion2Euler(e_eps)
        d_theta_dxi = np.array([[(phi_at_e_eps - phi_at_e) / eps],
                                [(theta_at_e_eps - theta_at_e) / eps],
                                [(psi_at_e_eps - psi_at_e_eps) / eps]])
        dtheta_de[:, i] = d_theta_dxi[:, 0]
    eye3_3 = np.eye(3)
    zero3_3 = np.zeros((3, 3))
    zero3_4 = np.zeros((3, 4))
    R1 = np.concatenate((eye3_3, zero3_3, zero3_4, zero3_3), 1)
    R2 = np.concatenate((zero3_3, eye3_3, zero3_4, zero3_3), 1)
    R3 = np.concatenate((zero3_3, zero3_3, dtheta_de, zero3_3), 1)
    R4 = np.concatenate((zero3_3, zero3_3, zero3_4, eye3_3), 1)
    dT_dxq = np.concatenate((R1, R2, R3, R4), 0)
    return dT_dxq
예제 #2
0
def euler_state(x_quat):
    # convert state x with attitude represented by quaternion
    # to x_euler with attitude represented by Euler angles
    phi, theta, psi = Quaternion2Euler(x_quat[6:10])
    x_euler = np.array([[x_quat[0]], [x_quat[1]], [x_quat[2]], [x_quat[3]],
                        [x_quat[4]], [x_quat[5]], [phi], [theta], [psi],
                        [x_quat[10]], [x_quat[11]], [x_quat[12]]])
    return x_euler
예제 #3
0
 def _update_msg_true_state(self):
     # update the true state message:
     phi, theta, psi = Quaternion2Euler(self._state[6:10])
     self.msg_true_state.pn = self._state.item(0)
     self.msg_true_state.pe = self._state.item(1)
     self.msg_true_state.h = -self._state.item(2)
     self.msg_true_state.phi = phi
     self.msg_true_state.theta = theta
     self.msg_true_state.psi = psi
     self.msg_true_state.p = self._state.item(10)
     self.msg_true_state.q = self._state.item(11)
     self.msg_true_state.r = self._state.item(12)
예제 #4
0
 def update_sensors(self):
     "Return value of sensors on MAV: gyros, accels, static_pressure, dynamic_pressure, GPS"
     phi, theta, psi = Quaternion2Euler(self._state[6:10])
     self.sensors.gyro_x = self._state.item(
         10) + SENSOR.gyro_x_bias + SENSOR.gyro_sigma * np.random.randn()
     self.sensors.gyro_y = self._state.item(
         11) + SENSOR.gyro_y_bias + SENSOR.gyro_sigma * np.random.randn()
     self.sensors.gyro_z = self._state.item(
         12) + SENSOR.gyro_z_bias + SENSOR.gyro_sigma * np.random.randn()
     self.sensors.accel_x = self._forces[
         0] / MAV.mass + MAV.gravity * np.sin(
             theta) + SENSOR.accel_sigma * np.random.randn()
     self.sensors.accel_y = self._forces[
         1] / MAV.mass - MAV.gravity * np.cos(theta) * np.sin(
             phi) + SENSOR.accel_sigma * np.random.randn()
     self.sensors.accel_z = self._forces[
         2] / MAV.mass - MAV.gravity * np.cos(theta) * np.cos(
             phi) + SENSOR.accel_sigma * np.random.randn()
     self.sensors.static_pressure = MAV.rho * MAV.gravity * -self._state.item(
         2) + SENSOR.static_pres_sigma * np.random.randn()
     self.sensors.diff_pressure = MAV.rho * self._Va**2 / 2. + SENSOR.diff_pres_sigma * np.random.randn(
     )
     # self.sensors.mag = Quaternion2Rotation(self._state[6:10]).T@Euler2Rotation(0,-66*np.pi/180.,12.5*np.pi/180.)@np.array([[1.],[0.],[0.]]) \
     #                    + SENSOR.mag_beta + np.random.normal(0, SENSOR.mag_sigma, 1)
     if self._t_gps >= SENSOR.ts_gps:
         self._gps_eta_n = np.exp(
             -SENSOR.gps_beta * SENSOR.ts_gps
         ) * self._gps_eta_n + SENSOR.gps_n_sigma * np.random.randn()
         self._gps_eta_e = np.exp(
             -SENSOR.gps_beta * SENSOR.ts_gps
         ) * self._gps_eta_e + SENSOR.gps_e_sigma * np.random.randn()
         self._gps_eta_h = np.exp(
             -SENSOR.gps_beta * SENSOR.ts_gps
         ) * self._gps_eta_h + SENSOR.gps_h_sigma * np.random.randn()
         self.sensors.gps_n = self._state.item(0) + self._gps_eta_n
         self.sensors.gps_e = self._state.item(1) + self._gps_eta_e
         self.sensors.gps_h = self._state.item(2) + self._gps_eta_h
         self.sensors.gps_Vg = np.sqrt(
             (self._Va * np.cos(psi) + self._wind.item(0))**2 +
             (self._Va * np.sin(psi) + self._wind.item(1))**2
         ) + SENSOR.gps_Vg_sigma * np.random.randn()
         self.sensors.gps_course = np.arctan2(
             self._Va * np.sin(psi) + self._wind.item(1),
             self._Va * np.cos(psi) + self._wind.item(0)
         ) + SENSOR.gps_course_sigma * np.random.randn()
         self._t_gps = 0.
     else:
         self._t_gps += self._ts_simulation
     return self.sensors
예제 #5
0
def compute_ss_model(mav, trim_state, trim_input):
    A_q = df_dx(mav, trim_state, trim_input)
    B_q = df_du(mav, trim_state, trim_input)
    dT_dxq = dT_d_x_q(trim_state[6:10])
    phi, theta, psi = Quaternion2Euler(trim_state[6:10])
    dT_inv_dxq = dT_inv_d_x_q(phi, theta, psi)
    A_e = dT_dxq @ A_q @ dT_inv_dxq
    B_e = dT_dxq @ B_q

    A_lat = A_e[[[4], [9], [11], [6], [8]], [4, 9, 11, 6, 8]]
    B_lat = B_e[[[4], [9], [11], [6], [8]], [0, 2]]
    A_lon = A_e[[[3], [5], [10], [7], [2]], [3, 5, 10, 7, 2]]
    B_lon = B_e[[[3], [5], [10], [7], [2]], [1, 2]]
    A_lon[4, :] = A_lon[4, :] * -1.0

    return A_lon, B_lon, A_lat, B_lat  #B_lat completely right # 5,3 and 3,2 in A_lat wrong #A_lon close to right # B_lon right
예제 #6
0
def compute_tf_model(mav, trim_state, trim_input):
    # trim values
    phi, theta, psi = Quaternion2Euler(trim_state[6:10])
    T_phi_delta_a_a1 = -.5 * MAV.rho * mav._Va**2 * MAV.S_wing * MAV.b * MAV.C_p_p * MAV.b / (
        2. * mav._Va)  #What is SB??
    T_phi_delta_a_a2 = .5 * MAV.rho * mav._Va**2 * MAV.S_wing * MAV.b * MAV.C_p_delta_a
    T_chi_phi = MAV.gravity / mav._Vg
    T_theta_delta_e_a1 = (-MAV.rho * mav._Va**2 * MAV.c * MAV.S_wing /
                          (2. * MAV.Jy)) * MAV.C_m_q * MAV.c / (2. * mav._Va)
    T_theta_delta_e_a2 = (-MAV.rho * mav._Va**2 * MAV.c * MAV.S_wing /
                          (2. * MAV.Jy)) * MAV.C_m_alpha
    T_theta_delta_e_a3 = (MAV.rho * mav._Va**2 * MAV.c * MAV.S_wing /
                          (2. * MAV.Jy)) * MAV.C_m_delta_e
    T_h_theta = mav._Va
    T_h_Va = theta
    T_Va_delta_t_a1 = (MAV.rho*mav._Va*MAV.S_wing/MAV.mass)*(MAV.C_D_0 + MAV.C_D_alpha*mav._alpha + MAV.C_D_delta_e*trim_input[1]) \
                        - dT_dVa(mav, mav._Va, trim_input[3])/MAV.mass
    #Aren't they all about trim values?? What other Va use?
    T_Va_delta_t_a2 = dT_ddelta_t(
        mav, mav._Va, trim_input[3]
    ) / MAV.mass  #(MAV.rho*MAV.S_wing/MAV.mass)*C_prop*k**2*trim_input[3] #Where is k???
    T_Va_theta = MAV.gravity * np.cos(theta - mav._alpha)
    T_beta_delta_r_a1 = -MAV.rho * mav._Va * MAV.S_wing * MAV.C_Y_beta / (
        2. * MAV.mass)
    T_beta_delta_r_a2 = -MAV.rho * mav._Va * MAV.S_wing * MAV.C_Y_delta_r / (
        2. * MAV.mass)

    f = open('../chap5/tf_coefficients.py', 'w')
    f.write('T_phi_delta_a_a1 = ' + str(T_phi_delta_a_a1) + '\n')
    f.write('T_phi_delta_a_a2 = ' + str(T_phi_delta_a_a2) + '\n')
    f.write('T_chi_phi = ' + str(T_chi_phi) + '\n')
    f.write('T_theta_delta_e_a1 = ' + str(T_theta_delta_e_a1) + '\n')
    f.write('T_theta_delta_e_a2 = ' + str(T_theta_delta_e_a2) + '\n')
    f.write('T_theta_delta_e_a3 = ' + str(T_theta_delta_e_a3) + '\n')
    f.write('T_h_theta = ' + str(T_h_theta) + '\n')
    f.write('T_h_Va = ' + str(T_h_Va) + '\n')
    f.write('T_Va_delta_t_a1 = ' + str(T_Va_delta_t_a1) + '\n')
    f.write('T_Va_delta_t_a2 = ' + str(T_Va_delta_t_a2) + '\n')
    f.write('T_Va_theta = ' + str(T_Va_theta) + '\n')
    f.write('T_beta_delta_r_a1 = ' + str(T_beta_delta_r_a1) + '\n')
    f.write('T_beta_delta_r_a2 = ' + str(T_beta_delta_r_a2) + '\n')
    f.close()
예제 #7
0
 def _update_msg_true_state(self):
     # update the class structure for the true state:
     #   [pn, pe, h, Va, alpha, beta, phi, theta, chi, p, q, r, Vg, wn, we, psi, gyro_bx, gyro_by, gyro_bz]
     phi, theta, psi = Quaternion2Euler(self._state[6:10])
     self.msg_true_state.pn = self._state.item(0)
     self.msg_true_state.pe = self._state.item(1)
     self.msg_true_state.h = -self._state.item(2)
     self.msg_true_state.Va = self._Va
     self.msg_true_state.alpha = self._alpha
     self.msg_true_state.beta = self._beta
     self.msg_true_state.phi = phi
     self.msg_true_state.theta = theta
     self.msg_true_state.psi = psi
     self.msg_true_state.Vg = self._Vg
     self.msg_true_state.gamma = self._gamma
     self.msg_true_state.chi = self._chi
     self.msg_true_state.p = self._state.item(10)
     self.msg_true_state.q = self._state.item(11)
     self.msg_true_state.r = self._state.item(12)
     self.msg_true_state.wn = self._wind.item(0)
     self.msg_true_state.we = self._wind.item(1)
def _derivatives(state, delta, gamma, Va):

    # extract the states
    pn = state.item(0)
    pe = state.item(1)
    pd = state.item(2)
    u = state.item(3)
    v = state.item(4)
    w = state.item(5)
    e0 = state.item(6)
    e1 = state.item(7)
    e2 = state.item(8)
    e3 = state.item(9)
    phi, theta, psi = Quaternion2Euler(state[6:10])
    p = state.item(10)
    q = state.item(11)
    r = state.item(12)
    alpha = theta - gamma

    # Forces due to gravity
    # phi, theta, psi = Quaternion2Euler(self._state[6:10])
    # fx = -MAV.mass*MAV.gravity * np.sin(theta)
    # fy = MAV.mass*MAV.gravity*np.cos(theta)*np.sin(phi)
    # fz = MAV.mass*MAV.gravity*np.cos(theta)*np.cos(phi)
    fx = MAV.mass * MAV.gravity * 2 * (e1 * e3 - e2 * e0)
    fy = MAV.mass * MAV.gravity * 2 * (e2 * e3 + e1 * e0)
    fz = MAV.mass * MAV.gravity * (e3**2 + e0**2 - e1**2 - e2**2)

    # Forces due to aerodynamics
    cA = np.cos(alpha)
    sA = np.sin(alpha)
    Cd = MAV.C_D_p + (MAV.C_L_0 +
                      MAV.C_L_alpha * alpha)**2 / (np.pi * np.exp(1) * MAV.AR)
    sigmaA = (1 + np.exp(-MAV.M * (alpha - MAV.alpha0)) + np.exp(MAV.M * (alpha + MAV.alpha0))) \
             / ((1 + np.exp(-MAV.M * (alpha - MAV.alpha0))) * (1 + np.exp(MAV.M * (alpha + MAV.alpha0))))
    Cl = (1 - sigmaA) * (MAV.C_L_0 + MAV.C_L_alpha * alpha) + sigmaA * (
        2 * np.sign(alpha) * sA**2 * cA)
    Cx = -Cd * cA + Cl * sA
    Cxq = -MAV.C_D_q * cA + MAV.C_L_q * sA
    Cxdeltae = -MAV.C_D_delta_e * cA + MAV.C_L_delta_e * sA
    Cz = -Cd * sA - Cl * cA
    Czq = -MAV.C_D_q * sA - MAV.C_L_q * cA
    Czdeltae = -MAV.C_D_delta_e * sA - MAV.C_L_delta_e * cA
    fx += .5 * MAV.rho * Va**2 * MAV.S_wing * (Cx + Cxq * MAV.c * q /
                                               (2 * Va) + Cxdeltae * delta[1])
    fy += .5 * MAV.rho * Va ** 2 * MAV.S_wing * (
                MAV.C_Y_0 + MAV.C_Y_beta * 0. + MAV.C_Y_p * MAV.b * p / (2 * Va) \
                + MAV.C_Y_r * MAV.b * r / (2 * Va) + MAV.C_Y_delta_a * delta[0] + MAV.C_Y_delta_r *
                delta[2])
    fz += .5 * MAV.rho * Va**2 * MAV.S_wing * (Cz + Czq * MAV.c * q /
                                               (2 * Va) + Czdeltae * delta[1])
    l = .5 * MAV.rho * Va ** 2 * MAV.S_wing * (MAV.b * (
                MAV.C_ell_0 + MAV.C_ell_beta * 0. + MAV.C_ell_p * MAV.b * p / (2 * Va) \
                + MAV.C_ell_r * MAV.b * r / (2 * Va) + MAV.C_ell_delta_a * delta[
                    0] + MAV.C_ell_delta_r * delta[2]))
    m = .5 * MAV.rho * Va**2 * MAV.S_wing * (
        MAV.c * (MAV.C_m_0 + MAV.C_m_alpha * alpha + MAV.C_m_q * MAV.c * q /
                 (2 * Va) + MAV.C_m_delta_e * delta[1]))
    n = .5 * MAV.rho * Va ** 2 * MAV.S_wing * (
                MAV.b * (MAV.C_n_0 + MAV.C_n_beta * 0. + MAV.C_n_p * MAV.b * p / (2 * Va) \
                         + MAV.C_n_r * MAV.b * r / (2 * Va) + MAV.C_n_delta_a * delta[
                             0] + MAV.C_n_delta_r * delta[2]))

    # Compute thrust and torque due to propeller
    # map delta_t throttle command (0 to 1) into motor input voltage
    V_in = MAV.V_max * delta[3]
    # Quadratic formula to solve for motor speed
    a = MAV.C_Q0 * MAV.rho * np.power(MAV.D_prop, 5) \
        / ((2. * np.pi) ** 2)
    b = (MAV.C_Q1 * MAV.rho * np.power(MAV.D_prop, 4) \
         / (2. * np.pi)) * Va + MAV.KQ ** 2 / MAV.R_motor
    c = MAV.C_Q2 * MAV.rho * np.power(MAV.D_prop, 3) \
        * Va ** 2 - (MAV.KQ / MAV.R_motor) * V_in + MAV.KQ * MAV.i0
    # Consider only positive _rotate_points
    Omega_op = (-b + np.sqrt(b**2. - 4. * a * c)) / (2. * a)
    # compute advance ratio
    J_op = 2. * np.pi * Va / (Omega_op * MAV.D_prop)
    # compute non-dimensionalized coefficients of thrust and torque
    C_T = MAV.C_T2 * J_op**2 + MAV.C_T1 * J_op + MAV.C_T0
    C_Q = MAV.C_Q2 * J_op**2 + MAV.C_Q1 * J_op + MAV.C_Q0
    # add thrust and torque due to propeller
    n = Omega_op / (2 * np.pi)
    fx += MAV.rho * n**2 * np.power(MAV.D_prop, 4) * C_T
    l += -MAV.rho * n**2 * np.power(MAV.D_prop, 5) * C_Q
    """
    for the dynamics xdot = f(x, u), returns f(x, u)
    """

    #   extract forces/moments
    # fx = forces_moments.item(0)
    # fy = forces_moments.item(1)
    # fz = forces_moments.item(2)
    # l = forces_moments.item(3)
    # m = forces_moments.item(4)
    # n = forces_moments.item(5)

    # position kinematics
    pn_dot = (e1 ** 2 + e0 ** 2 - e2 ** 2 - e3 ** 2) * u + \
             (2 * (e1 * e2 - e3 * e0)) * v + \
             (2 * (e1 * e3 + e2 * e0)) * w
    pe_dot = (2 * (e1 * e2 + e3 * e0)) * u + \
             (e2 ** 2 + e0 ** 2 - e1 ** 2 - e3 ** 2) * v + \
             (2 * (e2 * e3 - e1 * e0)) * w
    pd_dot = (2 * (e1 * e3 - e2 * e0)) * u + \
             (2 * (e2 * e3 + e1 * e0)) * v + \
             (e3 ** 2 + e0 ** 2 - e1 ** 2 - e2 ** 2) * w

    # position dynamics
    u_dot = r * v - q * w + fx / MAV.mass
    v_dot = p * w - r * u + fy / MAV.mass
    w_dot = q * u - p * v + fz / MAV.mass

    # rotational kinematics
    e0_dot = (-p * e1 - q * e2 - r * e3) / 2
    e1_dot = (p * e0 + r * e2 - q * e3) / 2
    e2_dot = (q * e0 - r * e1 + p * e3) / 2
    e3_dot = (r * e0 + q * e1 - p * e2) / 2

    # rotatonal dynamics
    p_dot = MAV.gamma1 * p * q - MAV.gamma2 * q * r + MAV.gamma3 * l + MAV.gamma4 * n
    q_dot = MAV.gamma5 * p * r - MAV.gamma6 * (p**2 - r**2) + m / MAV.Jy
    r_dot = MAV.gamma7 * p * q - MAV.gamma1 * q * r + MAV.gamma4 * l + MAV.gamma8 * n

    # collect the derivative of the states
    x_dot = np.array([[
        pn_dot, pe_dot, pd_dot, u_dot, v_dot, w_dot, e0_dot, e1_dot, e2_dot,
        e3_dot, p_dot, q_dot, r_dot
    ]]).T
    return x_dot