Beispiel #1
0
def qekf_measurement_model(T, y, n, w):
    """Generate a weighted least squares measurement model.

    This is eq. 18 from [2].

    Args:
        T   3x3 rotation matrix describing the prior attitude
        y   3xm matrix of unit 3D vector observations
        n   3xm matrix of corresponding unit 3D reference vectors
        w   list of weights corresponding to y and n

    Returns:
        A 3x3 measurement Jacobian.
    """
    H = np.zeros((3, 3))

    for ii in range(y.shape[1]):

        # Measurement Jacobian: eq 18
        yx = pq.skew(y[0:3, ii])
        Tn = T.dot(n[0:3, ii])
        Tnx = pq.skew(Tn)
        H += w[ii] * (yx.dot(Tnx) + Tnx.dot(yx))

    return H
Beispiel #2
0
def qekf_measurement_covariance(T, y, n, w, sigma_y, sigma_n):
    """Generate a measurement covariance for the z vector by computing
    measurement covariances on the observations and reference vectors.

    The z vector is defined as the weighted sum of the cross-products
    of the observations and references. If

      B = \sum_{i=1}^n w_i y_i n_i^\top

    then

      \left[ z \times \right] = B^\top - B

    or alternatively,

      z = \sum_{i=1}^n w_i ( y_i \times n_i ) .

    This function first generates QUEST measurement model covariances
    for n and y (Eqs. 5(a) and 5(b) from [2]) and then uses these to
    produce a measurement covariance for z (Eq. 25 from [2]).

    The weights can be obtained using compute_weights(), or you can
    supply your own.

    Args:
        T        transformation matrix describing the prior attitude
        y        3xm matrix of unit vector observations
        n        3xm matrix of corresponding unit reference vectors
        a        array of measurement weights corresponding to y and n
        sigma_y  array of standard deviations for each unit vector observation
        sigma_n  array of standard deviations for each unit reference vector

    Returns:
        A weighted 3x3 measurement covariance.

    """
    R = np.zeros((3, 3))

    for ii in range(y.shape[1]):
        # QUEST measurement model: eq 5a, 5b
        Rnn = quest_measurement_covariance(n[:, ii], sigma_n[ii])
        Ryy = quest_measurement_covariance(y[:, ii], sigma_y[ii])

        yx = pq.skew(y[0:3, ii])
        Tn = T.dot(n[0:3, ii])
        Tnx = pq.skew(Tn)

        # Measurement covariance: eq 25
        yxT = yx.dot(T)
        R += (yxT.dot(Rnn.dot(yxT.T)) + Tnx.dot(Ryy.dot(Tnx.T))) * (4 *
                                                                    w[ii]**2)

    return R
Beispiel #3
0
    def F(self):
        x = self.x
        T_body_to_inrtl = np.identity(3)

        F = np.zeros((self.N, self.N))
        F[9:self.N, 9:self.N] = np.diag(-self.beta)

        F[0:3, 3:6] = np.identity(3)
        F[3:6, 0:3] = G(x.eci[0:3], x.mu_earth) + G(x.lci[0:3], x.mu_moon)
        F[3:6, 6:9] = -pq.skew(x.a_meas_inrtl).dot(T_body_to_inrtl)
        F[3:6, 9:12] = -T_body_to_inrtl

        F[6:9, 6:9] = -pq.skew(x.w_meas_inrtl)
        F[6:9, 12:15] = -np.identity(3)

        return F
Beispiel #4
0
    def horizon_update(self, x, P, rel, plot=False):
        if rel in ('earth', 399):
            body_id = 399
            r_pci = x.eci[0:3]
        elif rel in ('moon', 301):
            body_id = 301
            r_pci = x.lci[0:3]

        R_cam = horizon.covariance(x.time,
                                   body_id,
                                   fpa_size=x.params.horizon_fpa_size,
                                   fov=x.params.horizon_fov,
                                   theta_max=x.params.horizon_theta_max,
                                   sigma_pix=x.params.horizon_sigma_pix,
                                   n_max=x.params.horizon_n_max)

        if plot:
            from plot_lincov import plot_covariance
            import matplotlib.pyplot as plt
            T_lvlh = frames.compute_T_inrtl_to_lvlh(x.lci)[0:3, 0:3]
            plot_covariance(T_lvlh.dot(R).dot(T_lvlh.T),
                            xlabel='downtrack (m)',
                            ylabel='crosstrack (m)',
                            zlabel='radial (m)')
            plt.show()

        H = np.zeros((3, self.N))
        H[0:3, 0:3] = x.T_body_to_cam.dot(x.T_inrtl_to_body)
        H[0:3,
          6:9] = x.T_body_to_cam.dot(pq.skew(x.T_inrtl_to_body.dot(r_pci)))

        return H, R_cam
Beispiel #5
0
def noisify_line_of_sight_vector(u, sigma):
    """Add misalignment to a line-of-sight unit vector measurement.

    Args:
        u      unit vector measurement (length 3)
        sigma  standard deviation, either scalar or vector (length 3)

    Returns:
        A noisy unit vector (length 3).
    """
    # First rotate the u vector to be along z
    z = np.array([0.0, 0.0, 1.0])

    # get axis of rotation
    v = np.cross(u, z)
    v /= spl.norm(v)

    # Get angle about that axis
    theta = np.arccos(u.dot(z))
    T_z_to_u = pq.Quat.from_angle_axis(theta, *v).to_matrix()

    # Now produce a misalignment matrix
    e = npr.rand(3) * sigma
    T_misalign = np.identity(3) - pq.skew(e)

    u_noisy = T_z_to_u.dot(T_misalign.dot(z))
    return u_noisy / spl.norm(u_noisy)  # normalize it
Beispiel #6
0
    def dynamics_matrix(self, omega):
        """Linearize the dynamics at the current time point, using the current
        IMU measurements and the state.

        Args:
            omega   angular velocity measurement (see propagate())

        Returns:
            A square matrix of the same size as the state vector.

        """
        F = np.zeros((6, 6))
        F[0:3, 0:3] = -pq.skew(omega)
        F[0:3, 3:6] = -np.identity(3)
        F[3:6, 3:6] = -np.identity(3) / self.tau
        return F
## Scratch remove axis of rotation from quaternion
u = np.array([[0, 0, 1.]]).T
# u = np.random.random((3,1))
u /= norm(u)

psi_hist, yaw_hist, s_hist, v_hist, qz_hist, qx_hist, qy_hist = [], [], [], [], [], [], []
for i in tqdm(range(10000)):
    # qm0 = Quaternion.from_euler(0.0, 10.0, 2*np.pi*np.random.random() - np.pi)
    # qm0 = Quaternion.from_euler(0.0, np.pi*np.random.random() - np.pi/2.0, 0.0)
    qm0 = Quaternion.from_euler(2*np.pi*np.random.random() - np.pi, np.pi * np.random.random() - np.pi / 2.0, 0.0)
    # qm0 = Quaternion.from_euler(270.0 * np.pi / 180.0, 85.0 * np.pi / 180.0, 90.0 * np.pi / 180.0)
    # qm0 = Quaternion.random()

    w = qm0.rot(u)
    th = u.T.dot(w)
    ve = skew(u).dot(w)
    qp0 = Quaternion.exp(th * ve)

    epsilon = np.eye(3) * e

    t = u.T.dot(qm0.rot(u))
    v = skew(u).dot(qm0.rot(u))

    tv0 = u.T.dot(qm0.rot(u)) * (skew(u).dot(qm0.rot(u)))
    a_dtvdq = -v.dot(u.T.dot(qm0.R.T).dot(skew(u))) - t*skew(u).dot(qm0.R.T.dot(skew(u)))
    d_dtvdq = np.zeros_like(a_dtvdq)

    nd = norm(t * v)
    d0 = t * v
    qd0 = Quaternion.exp(d0)
    sk_tv = skew(t * v)
Beispiel #8
0

if __name__ == '__main__':

    import pyquat.random as pqr
    import numpy.random as npr

    q_inrtl_to_body = pq.Quat(1.0, -2.0, 3.0, 4.0).normalized()
    print("q_ib = {}".format(q_inrtl_to_body))

    ref_misalign = npr.randn(3) * 1e-6
    sun_obs_misalign = npr.randn(3) * 1e-5
    mag_obs_misalign = npr.randn(3) * 1e-5

    T_ref_err = np.identity(3)  #- pq.skew(ref_misalign)
    T_sun_obs_err = np.identity(3) - pq.skew(sun_obs_misalign)
    T_mag_obs_err = np.identity(3) - pq.skew(mag_obs_misalign)

    mag_truth = np.array([0.0, 0.1, 1.0])
    mag_truth /= spl.norm(mag_truth)

    sun_truth = np.array([0.5, 0.5, 0.02])
    sun_truth /= spl.norm(sun_truth)

    Tib = q_inrtl_to_body.to_matrix()

    mag_ref = T_ref_err.dot(mag_truth)
    mag_ref /= spl.norm(mag_ref)
    sun_ref = T_ref_err.dot(sun_truth)
    sun_ref /= spl.norm(sun_ref)