Beispiel #1
0
def integrate_der(q: np.ndarray, n_body: np.ndarray, dt: float):
    """
    Return the derivative of the integrated quaternion q as a function of previous time step q
    and rotational velocity
    :param q: quaternion
    :param n_body: rotational velocity vector
    :param dt: time step
    :return: q_der_q and q_der_n
    """

    q = utils.normalize(q)
    n_body_norm = utils.norm2(n_body)
    w_world = rate_matrix_world(q)

    q_hat = np.concatenate((
        np.array([np.cos(0.5 * n_body_norm * dt)]),
        np.sin(0.5 * n_body_norm * dt) * utils.normalize(n_body),
    ))
    q_hat_mat = matrix(q_hat)

    # derivative of q with respect to previous time step q
    q_der_q = q_hat_mat @ (np.eye(4) - q.reshape(-1,1) @ q.reshape(1,-1))

    # derivative of q with respect to rotational velocity
    q_der_n = dt * 0.5 * w_world.T

    return q_der_q, q_der_n
Beispiel #2
0
def to_axis_angle(q: np.ndarray):
    """
    Calculate axis rotation by angle from quaternion
    :param q: quaternion
    :return: axis
    :return: angle
    """

    q = utils.normalize(q)
    theta = 2 * np.arccos(q[0])
    axis = utils.normalize(q[1:])

    return axis, theta
Beispiel #3
0
def conjugate(q: np.ndarray):
    """
    Calculate quaternion conjugate
    :param q: quaternion
    :return: quaternion conjugate
    """

    return utils.normalize(np.multiply(q, np.array([1, -1, -1, -1])))
Beispiel #4
0
 def test_normalize(self):
     """
     Utilities:   Vector normalize
     """
     for i in range(10):
         x = 10. * np.random.rand(3)
         x_normalized = utils.normalize(x)
         x_norm = utils.norm2(x_normalized)
         if x_norm > 0.001:
             self.assertAlmostEqual(x_norm, 1., 6)
Beispiel #5
0
def from_axis_angle(axis: np.ndarray, theta: float):
    """
    Calculate quaternion from rotation by angle about axis
    :param axis: axis
    :param theta: angle
    :return: quaternion
    """

    return utils.normalize(np.concatenate((np.array([np.cos(theta / 2.)]),
                                           np.sin(theta / 2.) * axis)))
Beispiel #6
0
def integrate(q: np.ndarray, n_body: np.ndarray, dt: float):
    """
    Calculate integrate single time step unit quaternion
    :param q: quaternion
    :param n_body: rotational velocity in body frame
    :param dt: time step
    :return: quaternion at t+1
    """

    q = utils.normalize(q)
    n_body_norm = utils.norm2(n_body)

    q_hat = np.concatenate((
        np.array([np.cos(0.5 * n_body_norm * dt)]),
        np.sin(0.5 * n_body_norm * dt) * utils.normalize(n_body),
    ))

    q = product(q_hat, q)

    return q
Beispiel #7
0
def transform_inv(v: np.ndarray, q: np.ndarray):
    """
    Calculate quaternion conjugate
    :param v: vector
    :param q: quaternion
    :return: vector inverse-transformed by quaternion
    """
    q = utils.normalize(q)
    q_conj = conjugate(q)

    return transform(v, q_conj, q)
Beispiel #8
0
def to_rot_mat(q: np.ndarray):
    """
    Calculate rotation matrix from quaternion
    :param q: quaternion
    :return: rotation matrix
    """
    q = utils.normalize(q)

    return np.array([
        [q[0]**2 + q[1]**2 - q[2]**2 - q[3]**2, 2*(q[1]*q[2] + q[0]*q[3]), 2*(q[1]*q[3] - q[0]*q[2])],
        [2*(q[2]*q[1] - q[0]*q[3]), q[0]**2 + q[2]**2 - q[1]**2 - q[3]**2, 2*(q[2]*q[3] + q[0]*q[1])],
        [2*(q[3]*q[1] + q[0]*q[2]), 2*(q[3]*q[2] - q[0]*q[1]), q[0]**2 + q[3]**2 - q[1]**2 - q[2]**2],
    ])
Beispiel #9
0
def transform(v: np.ndarray, q: np.ndarray, q_conj: np.ndarray = None):
    """
    Calculate quaternion conjugate
    :param v: vector
    :param q: quaternion
    :param q_conj: optional conjugate quaternion
    :return: vector transformed by quaternion
    """
    q = utils.normalize(q)

    if q_conj is None:
        q_conj = conjugate(q)

    v_pad = np.concatenate((np.array([0.]), v))

    return product(q, product(v_pad, q_conj))[1:]
Beispiel #10
0
def rot_mat_der(q: np.ndarray, i_q: int = 0, b_inverse: bool = False):
    """
    Return the derivative of a rotation matrix wrt given element
    :param q: quaternion
    :param i_q: derivative with respect to element i_q
    :param b_inverse: boolean true to return derivative of inverse rotation matrix
    :return: r_der_qi derivative of rotation matrix wrt i_q
    """

    q = utils.normalize(q)
    u_dv_dt = -2 * q[i_q] * to_rot_mat(q)

    if i_q == 0:
        v_du_dt = 2 * np.array([
            [q[0],  q[3], -q[2]],
            [-q[3], q[0],  q[1]],
            [q[2], -q[1],  q[0]],
        ])
    elif i_q == 1:
        v_du_dt = 2 * np.array([
            [q[1],  q[2],  q[3]],
            [q[2], -q[1],  q[0]],
            [q[3], -q[0], -q[1]],
        ])
    elif i_q == 2:
        v_du_dt = 2 * np.array([
            [-q[2], q[1], -q[0]],
            [q[1],  q[2],  q[3]],
            [q[0],  q[3], -q[2]],
        ])
    elif i_q == 3:
        v_du_dt = 2 * np.array([
            [-q[3],  q[0], q[1]],
            [-q[0], -q[3], q[2]],
            [q[1],   q[2], q[3]],
        ])
    else:
        return np.nan * np.ones((3, 3))

    if b_inverse:
        return np.ascontiguousarray(np.add(u_dv_dt, v_du_dt).T)
    else:
        return np.add(u_dv_dt, v_du_dt)
Beispiel #11
0
def find_valid_maxima(image_cube, footprint, exclusion, low_threshold):
    '''
  Returns a 3D array that is true everywhere that image_cube
  has a local maxima except in regions marked for exclusion.

  '''

    # peak_local_max expects a normalized image (values between 0 and 1)
    normalized_image_cube = normalize(image_cube)

    maxima = peak_local_max(normalized_image_cube,
                            indices=False,
                            min_distance=1,
                            threshold_rel=0,
                            threshold_abs=0,
                            exclude_border=True,
                            footprint=footprint)

    return maxima & (~exclusion) & (image_cube >= low_threshold)
Beispiel #12
0

if __name__ == '__main__':

    t = np.arange(0, T_MAX, DT)

    # target trajectory
    tgt = np.zeros((len(t), 4))
    tgt[:, 0] = 0. * np.ones_like(t)
    tgt[:, 1] = 0. * np.ones_like(t)
    tgt[:, 2] = 5. * np.ones_like(t)

    psi = 1. * np.pi / 4.

    if MODE == "Pitch":
        axis = utils.normalize(np.array([0., 1., 0.]))
    elif MODE == "Roll":
        axis = utils.normalize(np.array([1., 0., 0.]))
    elif MODE == "Yaw":
        axis = utils.normalize(np.array([0., 0., 1.]))
    else:
        raise Exception("Unrecognised mode")

    # initial conditions
    s0 = np.zeros(17)
    s0[drone.State.x.value] = 0.
    s0[drone.State.y.value] = 0.
    s0[drone.State.z.value] = 5.
    s0[drone.State.q_0.value] = np.cos(psi / 2.)
    s0[drone.State.q_i.value] = np.sin(psi / 2.) * axis[0]
    s0[drone.State.q_j.value] = np.sin(psi / 2.) * axis[1]
Beispiel #13
0
def madgwick(sensor_state: Sensor, filter_state: Filter, dt: float):

    # get working variables
    q = filter_state.s[3:7]
    gain = filter_state.r_madgwick_gain
    g_accel = sensor_state.accelerometer
    n_gyro = sensor_state.gyroscope
    e_magnet = sensor_state.magnetometer

    # find length of vectors
    g_norm = utils.norm2(g_accel)
    e_norm = utils.norm2(e_magnet)

    if (g_norm > 0.01) and (e_norm > 0.01):
        # normalize
        g_accel = g_accel / g_norm
        e_magnet = e_magnet / e_norm

        h = quaternion.transform(e_magnet, q)
        b = np.array([0., utils.norm2(h[0:2]), 0., h[2]])

        # gradient descent step
        f = np.array([
            2 * (q[1] * q[3] - q[0] * q[2]) - g_accel[0],
            2 * (q[0] * q[1] + q[2] * q[3]) - g_accel[1],
            2 * (0.5 - q[1]**2 - q[2]**2) - g_accel[2],
            2 * b[1] * (0.5 - q[2]**2 - q[3]**2) + 2 * b[3] *
            (q[1] * q[3] - q[0] * q[2]) - e_magnet[0],
            2 * b[1] * (q[1] * q[2] - q[0] * q[3]) + 2 * b[3] *
            (q[0] * q[1] + q[2] * q[3]) - e_magnet[1],
            2 * b[1] * (q[0] * q[2] + q[1] * q[3]) + 2 * b[3] *
            (0.5 - q[1]**2 - q[2]**2) - e_magnet[2],
        ])

        j = np.array([
            [-2 * q[2], 2 * q[3], -2 * q[0], 2 * q[1]],
            [2 * q[1], 2 * q[0], 2 * q[3], 2 * q[2]],
            [0, -4 * q[1], -4 * q[2], 0],
            [
                -2 * b[3] * q[2], 2 * b[3] * q[3],
                -4 * b[1] * q[2] - 2 * b[3] * q[0],
                -4 * b[1] * q[3] + 2 * b[3] * q[1]
            ],
            [
                -2 * b[1] * q[3] + 2 * b[3] * q[1],
                2 * b[1] * q[2] + 2 * b[3] * q[0],
                2 * b[1] * q[1] + 2 * b[3] * q[3],
                -2 * b[1] * q[0] + 2 * b[3] * q[2]
            ],
            [
                2 * b[1] * q[2], 2 * b[1] * q[3] - 4 * b[3] * q[1],
                2 * b[1] * q[0] - 4 * b[3] * q[2], 2 * b[1] * q[1]
            ],
        ])

        # get step update from accelerometer and magnetometer
        o_step = -1 * gain * utils.normalize(j.T @ f)

        w_body = quaternion.rate_matrix_body(q)
        n_step = quaternion.to_angular_velocity(w_body, o_step)

    else:
        n_step = np.zeros(3)

    # integrate
    n_body = n_gyro + n_step
    q = quaternion.integrate(q, n_body, dt)

    return q, n_body