def exponential_matrix(self, rot_vec):
        """
        Compute the exponential of the rotation matrix
        represented by rot_vec.

        :param rot_vec: 3D rotation vector
        :returns exponential_mat: 3x3 matrix
        """

        rot_vec = self.rotations.regularize(rot_vec)
        n_rot_vecs, _ = rot_vec.shape

        angle = gs.linalg.norm(rot_vec, axis=1)
        angle = gs.to_ndarray(angle, to_ndim=2, axis=1)

        skew_rot_vec = so_group.skew_matrix_from_vector(rot_vec)

        coef_1 = gs.empty_like(angle)
        coef_2 = gs.empty_like(coef_1)

        mask_0 = gs.equal(angle, 0)
        mask_0 = gs.squeeze(mask_0, axis=1)
        mask_close_to_0 = gs.isclose(angle, 0)
        mask_close_to_0 = gs.squeeze(mask_close_to_0, axis=1)
        mask_else = ~mask_0 & ~mask_close_to_0

        coef_1[mask_close_to_0] = (1. / 2.
                                   - angle[mask_close_to_0] ** 2 / 24.)
        coef_2[mask_close_to_0] = (1. / 6.
                                   - angle[mask_close_to_0] ** 3 / 120.)

        # TODO(nina): check if the discountinuity as 0 is expected.
        coef_1[mask_0] = 0
        coef_2[mask_0] = 0

        coef_1[mask_else] = (angle[mask_else] ** (-2)
                             * (1. - gs.cos(angle[mask_else])))
        coef_2[mask_else] = (angle[mask_else] ** (-2)
                             * (1. - (gs.sin(angle[mask_else])
                                      / angle[mask_else])))

        term_1 = gs.zeros((n_rot_vecs, self.n, self.n))
        term_2 = gs.zeros_like(term_1)

        for i in range(n_rot_vecs):
            term_1[i] = gs.eye(self.n) + skew_rot_vec[i] * coef_1[i]
            term_2[i] = gs.matmul(skew_rot_vec[i], skew_rot_vec[i]) * coef_2[i]

        exponential_mat = term_1 + term_2
        assert exponential_mat.ndim == 3

        return exponential_mat
    def jacobian_translation(self, point, left_or_right='left'):
        """
        Compute the jacobian matrix of the differential
        of the left/right translations
        from the identity to point in the Lie group SE(3).

        :param point: 6D vector element of SE(3)
        :returns jacobian: 6x6 matrix
        """
        assert self.belongs(point)
        assert left_or_right in ('left', 'right')

        dim = self.dimension
        rotations = self.rotations
        dim_rotations = rotations.dimension

        point = self.regularize(point)
        n_points, _ = point.shape

        rot_vec = point[:, :dim_rotations]

        jacobian = np.zeros((n_points,) + (dim,) * 2)

        if left_or_right == 'left':
            jacobian_rot = self.rotations.jacobian_translation(
                                                      point=rot_vec,
                                                      left_or_right='left')
            jacobian_trans = self.rotations.matrix_from_rotation_vector(
                    rot_vec)

            jacobian[:, :dim_rotations, :dim_rotations] = jacobian_rot
            jacobian[:, dim_rotations:, dim_rotations:] = jacobian_trans

        else:
            jacobian_rot = self.rotations.jacobian_translation(
                                                      point=rot_vec,
                                                      left_or_right='right')

            inv_skew_mat = - so_group.skew_matrix_from_vector(rot_vec)
            jacobian[:, :dim_rotations, :dim_rotations] = jacobian_rot
            jacobian[:, dim_rotations:, :dim_rotations] = inv_skew_mat
            jacobian[:, dim_rotations:, dim_rotations:] = np.eye(self.n)

        assert jacobian.ndim == 3
        return jacobian
Example #3
0
    def group_log_from_identity(self, point):
        """
        Compute the group logarithm of the point at the identity.
        """
        assert self.belongs(point)
        point = self.regularize(point)

        rotations = self.rotations
        dim_rotations = rotations.dimension

        rot_vec = point[:, :dim_rotations]
        angle = gs.linalg.norm(rot_vec, axis=1)
        angle = gs.to_ndarray(angle, to_ndim=2, axis=1)

        translation = point[:, dim_rotations:]

        group_log = gs.zeros_like(point)
        group_log[:, :dim_rotations] = rot_vec
        skew_rot_vec = so_group.skew_matrix_from_vector(rot_vec)
        sq_skew_rot_vec = gs.matmul(skew_rot_vec, skew_rot_vec)

        mask_close_0 = gs.isclose(angle, 0)
        mask_close_0 = gs.squeeze(mask_close_0, axis=1)

        mask_close_pi = gs.isclose(angle, gs.pi)
        mask_close_pi = gs.squeeze(mask_close_pi, axis=1)

        mask_else = ~mask_close_0 & ~mask_close_pi

        coef_1 = - 0.5 * gs.ones_like(angle)
        coef_2 = gs.zeros_like(angle)

        coef_2[mask_close_0] = (1. / 12. + angle[mask_close_0] ** 2 / 720.
                                + angle[mask_close_0] ** 4 / 30240.
                                + angle[mask_close_0] ** 6 / 1209600.)

        delta_angle = angle[mask_close_pi] - gs.pi
        coef_2[mask_close_pi] = (1. / PI2
                                 + (PI2 - 8.) * delta_angle / (4. * PI3)
                                 - ((PI2 - 12.)
                                    * delta_angle ** 2 / (4. * PI4))
                                 + ((-192. + 12. * PI2 + PI4)
                                    * delta_angle ** 3 / (48. * PI5))
                                 - ((-240. + 12. * PI2 + PI4)
                                    * delta_angle ** 4 / (48. * PI6))
                                 + ((-2880. + 120. * PI2 + 10. * PI4 + PI6)
                                    * delta_angle ** 5 / (480. * PI7))
                                 - ((-3360 + 120. * PI2 + 10. * PI4 + PI6)
                                    * delta_angle ** 6 / (480. * PI8)))

        psi = (0.5 * angle[mask_else]
               * gs.sin(angle[mask_else]) / (1 - gs.cos(angle[mask_else])))
        coef_2[mask_else] = (1 - psi) / (angle[mask_else] ** 2)

        n_points, _ = point.shape
        group_log_translation = gs.zeros((n_points, self.n))
        for i in range(n_points):
            translation_i = translation[i]
            term_1_i = coef_1[i] * gs.dot(translation_i,
                                          gs.transpose(skew_rot_vec[i]))
            term_2_i = coef_2[i] * gs.dot(translation_i,
                                          gs.transpose(sq_skew_rot_vec[i]))
            group_log_translation[i] = translation_i + term_1_i + term_2_i

        group_log[:, dim_rotations:] = group_log_translation

        assert group_log.ndim == 2

        return group_log
Example #4
0
    def group_exp_from_identity(self, tangent_vec):
        """
        Compute the group exponential of the tangent vector at the identity.
        """
        tangent_vec = gs.to_ndarray(tangent_vec, to_ndim=2)

        rotations = self.rotations
        dim_rotations = rotations.dimension

        rot_vec = tangent_vec[:, :dim_rotations]
        rot_vec = self.rotations.regularize(rot_vec)
        translation = tangent_vec[:, dim_rotations:]

        angle = gs.linalg.norm(rot_vec, axis=1)
        angle = gs.to_ndarray(angle, to_ndim=2, axis=1)

        mask_close_pi = gs.isclose(angle, gs.pi)
        mask_close_pi = gs.squeeze(mask_close_pi, axis=1)
        rot_vec[mask_close_pi] = rotations.regularize(
                                       rot_vec[mask_close_pi])

        skew_mat = so_group.skew_matrix_from_vector(rot_vec)
        sq_skew_mat = gs.matmul(skew_mat, skew_mat)

        mask_0 = gs.equal(angle, 0)
        mask_close_0 = gs.isclose(angle, 0) & ~mask_0

        mask_0 = gs.squeeze(mask_0, axis=1)
        mask_close_0 = gs.squeeze(mask_close_0, axis=1)

        mask_else = ~mask_0 & ~mask_close_0

        coef_1 = gs.zeros_like(angle)
        coef_2 = gs.zeros_like(angle)

        coef_1[mask_0] = 1. / 2.
        coef_2[mask_0] = 1. / 6.

        coef_1[mask_close_0] = (1. / 2. - angle[mask_close_0] ** 2 / 24.
                                + angle[mask_close_0] ** 4 / 720.
                                - angle[mask_close_0] ** 6 / 40320.)
        coef_2[mask_close_0] = (1. / 6. - angle[mask_close_0] ** 2 / 120.
                                + angle[mask_close_0] ** 4 / 5040.
                                - angle[mask_close_0] ** 6 / 362880.)

        coef_1[mask_else] = ((1. - gs.cos(angle[mask_else]))
                             / angle[mask_else] ** 2)
        coef_2[mask_else] = ((angle[mask_else] - gs.sin(angle[mask_else]))
                             / angle[mask_else] ** 3)

        n_tangent_vecs, _ = tangent_vec.shape
        group_exp_translation = gs.zeros((n_tangent_vecs, self.n))
        for i in range(n_tangent_vecs):
            translation_i = translation[i]
            term_1_i = coef_1[i] * gs.dot(translation_i,
                                          gs.transpose(skew_mat[i]))
            term_2_i = coef_2[i] * gs.dot(translation_i,
                                          gs.transpose(sq_skew_mat[i]))

            group_exp_translation[i] = translation_i + term_1_i + term_2_i

        group_exp = gs.zeros_like(tangent_vec)
        group_exp[:, :dim_rotations] = rot_vec
        group_exp[:, dim_rotations:] = group_exp_translation

        group_exp = self.regularize(group_exp)
        return group_exp
    def group_exp_from_identity(self,
                                tangent_vec):
        """
        Compute the group exponential of vector tangent_vector,
        at point base_point.

        :param tangent_vector: tangent vector of SE(3) at base_point.
        :param base_point: 6d vector element of SE(3).
        :returns group_exp: 6d vector element of SE(3).
        """
        tangent_vec = vectorization.expand_dims(tangent_vec, to_ndim=2)

        rotations = self.rotations
        dim_rotations = rotations.dimension

        rot_vec = tangent_vec[:, :dim_rotations]
        rot_vec = self.rotations.regularize(rot_vec)
        translation = tangent_vec[:, dim_rotations:]

        angle = np.linalg.norm(rot_vec, axis=1)
        angle = vectorization.expand_dims(angle, to_ndim=2, axis=1)

        mask_close_pi = np.isclose(angle, np.pi)
        mask_close_pi = np.squeeze(mask_close_pi, axis=1)
        rot_vec[mask_close_pi] = rotations.regularize(
                                       rot_vec[mask_close_pi])

        skew_mat = so_group.skew_matrix_from_vector(rot_vec)
        sq_skew_mat = np.matmul(skew_mat, skew_mat)

        mask_0 = np.equal(angle, 0)
        mask_close_0 = np.isclose(angle, 0) & ~mask_0

        mask_0 = np.squeeze(mask_0, axis=1)
        mask_close_0 = np.squeeze(mask_close_0, axis=1)

        mask_else = ~mask_0 & ~mask_close_0

        coef_1 = np.zeros_like(angle)
        coef_2 = np.zeros_like(angle)

        coef_1[mask_0] = 1. / 2.
        coef_2[mask_0] = 1. / 6.

        coef_1[mask_close_0] = (1. / 2. - angle[mask_close_0] ** 2 / 24.
                                + angle[mask_close_0] ** 4 / 720.
                                - angle[mask_close_0] ** 6 / 40320.)
        coef_2[mask_close_0] = (1. / 6. - angle[mask_close_0] ** 2 / 120.
                                + angle[mask_close_0] ** 4 / 5040.
                                - angle[mask_close_0] ** 6 / 362880.)

        coef_1[mask_else] = ((1. - np.cos(angle[mask_else]))
                             / angle[mask_else] ** 2)
        coef_2[mask_else] = ((angle[mask_else] - np.sin(angle[mask_else]))
                             / angle[mask_else] ** 3)

        n_tangent_vecs, _ = tangent_vec.shape
        group_exp_translation = np.zeros((n_tangent_vecs, self.n))
        for i in range(n_tangent_vecs):
            translation_i = translation[i]
            term_1_i = coef_1[i] * np.dot(translation_i,
                                          np.transpose(skew_mat[i]))
            term_2_i = coef_2[i] * np.dot(translation_i,
                                          np.transpose(sq_skew_mat[i]))

            group_exp_translation[i] = translation_i + term_1_i + term_2_i

        group_exp = np.zeros_like(tangent_vec)
        group_exp[:, :dim_rotations] = rot_vec
        group_exp[:, dim_rotations:] = group_exp_translation

        group_exp = self.regularize(group_exp)
        return group_exp