-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | 3d math including quaternions/euler angles/dcms and utility functions -- -- This is a port of my mathlib C library: -- `https://github.com/ghorn/mathlib` @package spatial-math @version 0.3.1.0 module SpatialMath -- | 3-2-1 Euler angle rotation sequence data Euler a Euler :: a -> a -> a -> Euler a [eYaw] :: Euler a -> a [ePitch] :: Euler a -> a [eRoll] :: Euler a -> a -- | doesn't require RealFloat, used for overloading symbolics class Floating a => ArcTan2 a arctan2 :: ArcTan2 a => a -> a -> a -- | Rotate a vector about the X axis -- --
-- >>> trunc $ rotateXyzAboutX (V3 0 1 0) (pi/2) -- V3 0.0 0.0 1.0 ---- --
-- >>> trunc $ rotateXyzAboutX (V3 0 0 1) (pi/2) -- V3 0.0 (-1.0) 0.0 --rotateXyzAboutX :: Floating a => V3 a -> a -> V3 a -- | Rotate a vector about the Y axis -- --
-- >>> trunc $ rotateXyzAboutY (V3 0 0 1) (pi/2) -- V3 1.0 0.0 0.0 ---- --
-- >>> trunc $ rotateXyzAboutY (V3 1 0 0) (pi/2) -- V3 0.0 0.0 (-1.0) --rotateXyzAboutY :: Floating a => V3 a -> a -> V3 a -- | Rotate a vector about the Z axis -- --
-- >>> trunc $ rotateXyzAboutZ (V3 1 0 0) (pi/2) -- V3 0.0 1.0 0.0 ---- --
-- >>> trunc $ rotateXyzAboutZ (V3 0 1 0) (pi/2) -- V3 (-1.0) 0.0 0.0 --rotateXyzAboutZ :: Floating a => V3 a -> a -> V3 a -- | Convert quaternion to Euler angles -- --
-- >>> euler321OfQuat (Quaternion 1.0 (V3 0.0 0.0 0.0))
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> euler321OfQuat (Quaternion (sqrt(2)/2) (V3 (sqrt(2)/2) 0.0 0.0))
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 1.5707963267948966}
--
--
--
-- >>> euler321OfQuat (Quaternion (sqrt(2)/2) (V3 0.0 (sqrt(2)/2) 0.0))
-- Euler {eYaw = 0.0, ePitch = 1.5707963267948966, eRoll = 0.0}
--
--
--
-- >>> euler321OfQuat (Quaternion (sqrt(2)/2) (V3 0.0 0.0 (sqrt(2)/2)))
-- Euler {eYaw = 1.5707963267948966, ePitch = -0.0, eRoll = 0.0}
--
euler321OfQuat :: (ArcTan2 a, Ord a) => Quaternion a -> Euler a
-- | Convert quaternion to Euler angles. Returns Nan if 2.0*(q1*q3 - q0*q2)
-- is outside [-1, 1].
--
--
-- >>> unsafeEuler321OfQuat (Quaternion 1.0 (V3 0.0 0.0 0.0))
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> unsafeEuler321OfQuat (Quaternion (sqrt(2)/2) (V3 (sqrt(2)/2) 0.0 0.0))
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 1.5707963267948966}
--
--
--
-- >>> unsafeEuler321OfQuat (Quaternion (sqrt(2)/2) (V3 0.0 (sqrt(2)/2) 0.0))
-- Euler {eYaw = 0.0, ePitch = NaN, eRoll = 0.0}
--
--
--
-- >>> unsafeEuler321OfQuat (Quaternion (sqrt(2)/2) (V3 0.0 0.0 (sqrt(2)/2)))
-- Euler {eYaw = 1.5707963267948966, ePitch = -0.0, eRoll = 0.0}
--
unsafeEuler321OfQuat :: ArcTan2 a => Quaternion a -> Euler a
-- | Convert DCM to euler angles
--
--
-- >>> euler321OfDcm $ V3 (V3 1 0 0) (V3 0 1 0) (V3 0 0 1)
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> euler321OfDcm $ V3 (V3 0 1 0) (V3 (-1) 0 0) (V3 0 0 1)
-- Euler {eYaw = 1.5707963267948966, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> let s = sqrt(2)/2 in euler321OfDcm $ V3 (V3 s s 0) (V3 (-s) s 0) (V3 0 0 1)
-- Euler {eYaw = 0.7853981633974483, ePitch = -0.0, eRoll = 0.0}
--
euler321OfDcm :: (Ord a, ArcTan2 a) => M33 a -> Euler a
-- | Convert DCM to euler angles. Returns Nan if r[1,3] is outside [-1, 1].
--
--
-- >>> unsafeEuler321OfDcm $ V3 (V3 1 0 0) (V3 0 1 0) (V3 0 0 1)
-- Euler {eYaw = 0.0, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> unsafeEuler321OfDcm $ V3 (V3 0 1 0) (V3 (-1) 0 0) (V3 0 0 1)
-- Euler {eYaw = 1.5707963267948966, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> let s = sqrt(2)/2 in unsafeEuler321OfDcm $ V3 (V3 s s 0) (V3 (-s) s 0) (V3 0 0 1)
-- Euler {eYaw = 0.7853981633974483, ePitch = -0.0, eRoll = 0.0}
--
--
--
-- >>> unsafeEuler321OfDcm $ V3 (V3 0 0 1.1) (V3 0 0 0) (V3 0 0 0)
-- Euler {eYaw = 0.0, ePitch = NaN, eRoll = 0.0}
--
unsafeEuler321OfDcm :: ArcTan2 a => M33 a -> Euler a
-- | Convert Euler angles to quaternion. The scalar part of the result may
-- be positive or negative.
--
-- -- >>> quatOfEuler321 (Euler 0 0 0) -- Quaternion 1.0 (V3 0.0 0.0 0.0) ---- --
-- >>> quatOfEuler321 (Euler (pi/2) 0 0) -- Quaternion 0.7071067811865476 (V3 0.0 0.0 0.7071067811865475) ---- --
-- >>> quatOfEuler321 (Euler 0 (pi/2) 0) -- Quaternion 0.7071067811865476 (V3 0.0 0.7071067811865475 0.0) ---- --
-- >>> quatOfEuler321 (Euler 0 0 (pi/2)) -- Quaternion 0.7071067811865476 (V3 0.7071067811865475 0.0 0.0) --quatOfEuler321 :: Floating a => Euler a -> Quaternion a -- | convert a quaternion to a DCM -- --
-- >>> dcmOfQuat $ Quaternion 1.0 (V3 0.0 0.0 0.0) -- V3 (V3 1.0 0.0 0.0) (V3 0.0 1.0 0.0) (V3 0.0 0.0 1.0) ---- --
-- >>> let s = sqrt(2)/2 in fmap trunc $ dcmOfQuat $ Quaternion s (V3 0.0 0.0 s) -- V3 (V3 0.0 1.0 0.0) (V3 (-1.0) 0.0 0.0) (V3 0.0 0.0 1.0) ---- --
-- >>> dcmOfQuat $ Quaternion 0.9238795325112867 (V3 0.0 0.0 0.3826834323650898) -- V3 (V3 0.7071067811865475 0.7071067811865476 0.0) (V3 (-0.7071067811865476) 0.7071067811865475 0.0) (V3 0.0 0.0 1.0) --dcmOfQuat :: Num a => Quaternion a -> M33 a dcmOfQuatB2A :: Num a => Quaternion a -> M33 a -- | Convert DCM to euler angles -- --
-- >>> fmap trunc $ dcmOfEuler321 $ Euler {eYaw = 0.0, ePitch = 0, eRoll = 0}
-- V3 (V3 1.0 0.0 0.0) (V3 0.0 1.0 0.0) (V3 0.0 0.0 1.0)
--
--
--
-- >>> fmap trunc $ dcmOfEuler321 $ Euler {eYaw = pi/2, ePitch = 0, eRoll = 0}
-- V3 (V3 0.0 1.0 0.0) (V3 (-1.0) 0.0 0.0) (V3 0.0 0.0 1.0)
--
--
--
-- >>> fmap trunc $ dcmOfEuler321 $ Euler {eYaw = pi/4, ePitch = 0, eRoll = 0}
-- V3 (V3 0.7071067811865476 0.7071067811865475 0.0) (V3 (-0.7071067811865475) 0.7071067811865476 0.0) (V3 0.0 0.0 1.0)
--
dcmOfEuler321 :: Floating a => Euler a -> M33 a
-- | convert a DCM to a quaternion
--
-- -- >>> quatOfDcm $ V3 (V3 1 0 0) (V3 0 1 0) (V3 0 0 1) -- Quaternion 1.0 (V3 (-0.0) (-0.0) (-0.0)) ---- --
-- >>> quatOfDcm $ V3 (V3 0 1 0) (V3 (-1) 0 0) (V3 0 0 1) -- Quaternion 0.7071067811865477 (V3 (-0.0) (-0.0) 0.7071067811865474) ---- --
-- >>> let s = sqrt(2)/2 in quatOfDcm $ V3 (V3 s s 0) (V3 (-s) s 0) (V3 0 0 1) -- Quaternion 0.9238795325112868 (V3 (-0.0) (-0.0) 0.3826834323650898) --quatOfDcm :: Floating a => M33 a -> Quaternion a quatOfDcmB2A :: Floating a => M33 a -> Quaternion a -- | vec_b = R_a2b * vec_a rotVecByDcm :: Num a => M33 a -> V3 a -> V3 a -- | vec_a = R_a2b^T * vec_b rotVecByDcmB2A :: Num a => M33 a -> V3 a -> V3 a -- | vec_b = q_a2b * vec_a * q_a2b^(-1) vec_b = R(q_a2b) * vec_a rotVecByQuat :: Num a => Quaternion a -> V3 a -> V3 a rotVecByQuatB2A :: Num a => Quaternion a -> V3 a -> V3 a rotVecByEuler :: (Floating a, Ord a) => Euler a -> V3 a -> V3 a rotVecByEulerB2A :: (Floating a, Ord a) => Euler a -> V3 a -> V3 a -- | A 3x3 matrix with row-major representation type M33 a = V3 (V3 a) -- | A 3-dimensional vector data V3 a :: * -> * V3 :: ~a -> ~a -> ~a -> V3 a -- | Quaternions data Quaternion a :: * -> * Quaternion :: ~a -> {-# UNPACK #-} ~(V3 a) -> Quaternion a instance SpatialMath.ArcTan2 GHC.Types.Double instance SpatialMath.ArcTan2 GHC.Types.Float module SpatialMathT -- | doesn't require RealFloat, used for overloading symbolics class Floating a => ArcTan2 a arctan2 :: ArcTan2 a => a -> a -> a -- | 3-2-1 Euler angle rotation sequence data Euler a Euler :: a -> a -> a -> Euler a [eYaw] :: Euler a -> a [ePitch] :: Euler a -> a [eRoll] :: Euler a -> a -- | Quaternions data Quaternion a :: * -> * Quaternion :: ~a -> {-# UNPACK #-} ~(V3 a) -> Quaternion a -- | A 3-dimensional vector data V3 a :: * -> * V3 :: ~a -> ~a -> ~a -> V3 a class Rotation g a compose :: Rotation g a => Rot f1 f2 g a -> Rot f2 f3 g a -> Rot f1 f3 g a rot :: Rotation g a => Rot f1 f2 g a -> V3T f1 a -> V3T f2 a rot' :: Rotation g a => Rot f1 f2 g a -> V3T f2 a -> V3T f1 a transpose :: Rotation g a => Rot f1 f2 g a -> Rot f2 f1 g a identity :: Rotation g a => Rot f1 f2 g a newtype Rot f1 f2 r a Rot :: r a -> Rot f1 f2 r a [unRot] :: Rot f1 f2 r a -> r a newtype V3T f a V3T :: V3 a -> V3T f a [unV] :: V3T f a -> V3 a -- | A space that has at least 1 basis vector _x. class R1 (t :: * -> *) -- |
-- >>> V1 2 ^._x -- 2 ---- --
-- >>> V1 2 & _x .~ 3 -- V1 3 --_x :: (R1 t, Functor f) => (a -> f a) -> t a -> f (t a) -- | A space that distinguishes 2 orthogonal basis vectors _x and -- _y, but may have more. class R1 t => R2 (t :: * -> *) -- |
-- >>> V2 1 2 ^._y -- 2 ---- --
-- >>> V2 1 2 & _y .~ 3 -- V2 1 3 --_y :: (R2 t, Functor f) => (a -> f a) -> t a -> f (t a) _xy :: (R2 t, Functor f) => (V2 a -> f (V2 a)) -> t a -> f (t a) -- | A space that distinguishes 3 orthogonal basis vectors: _x, -- _y, and _z. (It may have more) class R2 t => R3 (t :: * -> *) -- |
-- >>> V3 1 2 3 ^. _z -- 3 --_z :: (R3 t, Functor f) => (a -> f a) -> t a -> f (t a) _xyz :: (R3 t, Functor f) => (V3 a -> f (V3 a)) -> t a -> f (t a) cross :: Num a => V3T f a -> V3T f a -> V3T f a orthonormalize :: Floating a => Rot f1 f2 (V3 :. V3) a -> Rot f1 f2 (V3 :. V3) a dcmOfQuat :: Num a => Rot f g Quaternion a -> Rot f g (V3 :. V3) a dcmOfEuler321 :: Floating a => Rot f g Euler a -> Rot f g (V3 :. V3) a quatOfDcm :: Floating a => Rot f g (V3 :. V3) a -> Rot f g Quaternion a quatOfEuler321 :: Floating a => Rot f g Euler a -> Rot f g Quaternion a euler321OfDcm :: (ArcTan2 a, Ord a) => Rot f g (V3 :. V3) a -> Rot f g Euler a unsafeEuler321OfDcm :: ArcTan2 a => Rot f g (V3 :. V3) a -> Rot f g Euler a euler321OfQuat :: (ArcTan2 a, Ord a) => Rot f g Quaternion a -> Rot f g Euler a unsafeEuler321OfQuat :: ArcTan2 a => Rot f g Quaternion a -> Rot f g Euler a -- | Composition of unary type constructors -- -- There are (at least) two useful Monoid instances, so you'll -- have to pick one and type-specialize it (filling in all or parts of -- g and/or f). -- --
-- -- standard Monoid instance for Applicative applied to Monoid
-- instance (Applicative (g :. f), Monoid a) => Monoid ((g :. f) a) where
-- { mempty = pure mempty; mappend = liftA2 mappend }
-- -- Especially handy when g is a Monoid_f.
-- instance Monoid (g (f a)) => Monoid ((g :. f) a) where
-- { mempty = O mempty; mappend = inO2 mappend }
--
--
-- Corresponding to the first and second definitions above,
--
--
-- instance (Applicative g, Monoid_f f) => Monoid_f (g :. f) where
-- { mempty_f = O (pure mempty_f); mappend_f = inO2 (liftA2 mappend_f) }
-- instance Monoid_f g => Monoid_f (g :. f) where
-- { mempty_f = O mempty_f; mappend_f = inO2 mappend_f }
--
--
-- Similarly, there are two useful Functor instances and two
-- useful ContraFunctor instances.
--
-- -- instance ( Functor g, Functor f) => Functor (g :. f) where fmap = fmapFF -- instance (ContraFunctor g, ContraFunctor f) => Functor (g :. f) where fmap = fmapCC -- -- instance ( Functor g, ContraFunctor f) => ContraFunctor (g :. f) where contraFmap = contraFmapFC -- instance (ContraFunctor g, Functor f) => ContraFunctor (g :. f) where contraFmap = contraFmapCF ---- -- However, it's such a bother to define the Functor instances per -- composition type, I've left the fmapFF case in. If you want the fmapCC -- one, you're out of luck for now. I'd love to hear a good solution. -- Maybe someday Haskell will do Prolog-style search for instances, -- subgoaling the constraints, rather than just matching instance heads. newtype (:.) (g :: * -> *) (f :: * -> *) a :: (* -> *) -> (* -> *) -> * -> * O :: g (f a) -> (:.) a -- | Unwrap a '(:.)'. unO :: (:.) g f a -> g (f a) instance Data.Binary.Class.Binary (r a) => Data.Binary.Class.Binary (SpatialMathT.Rot f1 f2 r a) instance Data.Serialize.Serialize (r a) => Data.Serialize.Serialize (SpatialMathT.Rot f1 f2 r a) instance GHC.Generics.Generic (SpatialMathT.Rot f1 f2 r a) instance GHC.Generics.Generic1 (SpatialMathT.Rot f1 f2 r) instance GHC.Classes.Ord (r a) => GHC.Classes.Ord (SpatialMathT.Rot f1 f2 r a) instance GHC.Show.Show (r a) => GHC.Show.Show (SpatialMathT.Rot f1 f2 r a) instance GHC.Classes.Eq (r a) => GHC.Classes.Eq (SpatialMathT.Rot f1 f2 r a) instance GHC.Real.Fractional (r a) => GHC.Real.Fractional (SpatialMathT.Rot f1 f2 r a) instance GHC.Num.Num (r a) => GHC.Num.Num (SpatialMathT.Rot f1 f2 r a) instance Foreign.Storable.Storable (r a) => Foreign.Storable.Storable (SpatialMathT.Rot f1 f2 r a) instance GHC.Base.Applicative r => GHC.Base.Applicative (SpatialMathT.Rot f1 f2 r) instance Data.Traversable.Traversable r => Data.Traversable.Traversable (SpatialMathT.Rot f1 f2 r) instance Data.Foldable.Foldable r => Data.Foldable.Foldable (SpatialMathT.Rot f1 f2 r) instance GHC.Base.Functor r => GHC.Base.Functor (SpatialMathT.Rot f1 f2 r) instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (SpatialMathT.V3T f a) instance Data.Serialize.Serialize a => Data.Serialize.Serialize (SpatialMathT.V3T f a) instance GHC.Generics.Generic (SpatialMathT.V3T f a) instance GHC.Generics.Generic1 (SpatialMathT.V3T f) instance GHC.Classes.Ord a => GHC.Classes.Ord (SpatialMathT.V3T f a) instance GHC.Show.Show a => GHC.Show.Show (SpatialMathT.V3T f a) instance GHC.Classes.Eq a => GHC.Classes.Eq (SpatialMathT.V3T f a) instance GHC.Real.Fractional a => GHC.Real.Fractional (SpatialMathT.V3T f a) instance GHC.Num.Num a => GHC.Num.Num (SpatialMathT.V3T f a) instance Foreign.Storable.Storable a => Foreign.Storable.Storable (SpatialMathT.V3T f a) instance Linear.Metric.Metric (SpatialMathT.V3T f) instance Linear.Vector.Additive (SpatialMathT.V3T f) instance GHC.Base.Applicative (SpatialMathT.V3T f) instance Data.Traversable.Traversable (SpatialMathT.V3T f) instance Data.Foldable.Foldable (SpatialMathT.V3T f) instance GHC.Base.Functor (SpatialMathT.V3T f) instance Linear.V1.R1 (SpatialMathT.V3T f) instance Linear.V2.R2 (SpatialMathT.V3T f) instance Linear.V3.R3 (SpatialMathT.V3T f) instance GHC.Num.Num a => SpatialMathT.Rotation Linear.Quaternion.Quaternion a instance GHC.Num.Num a => SpatialMathT.Rotation (Linear.V3.V3 Control.Compose.:. Linear.V3.V3) a instance (SpatialMath.ArcTan2 a, GHC.Float.Floating a, GHC.Classes.Ord a) => SpatialMathT.Rotation Types.Euler a