sbp-0.50.3: src/SwiftNav/SBP/Navigation.hs
-- |
-- Module: SwiftNav.SBP.Navigation
-- Copyright: Copyright (C) 2015 Swift Navigation, Inc.
-- License: LGPL-3
-- Maintainer: Mark Fine <dev@swiftnav.com>
-- Stability: experimental
-- Portability: portable
--
-- Geodetic navigation messages reporting GPS time, position, velocity, and
-- baseline position solutions. For position solutions, these messages define
-- several different position solutions: single-point (SPP), RTK, and pseudo-
-- absolute position solutions. The SPP is the standalone, absolute GPS
-- position solution using only a single receiver. The RTK solution is the
-- differential GPS solution, which can use either a fixed/integer or floating
-- carrier phase ambiguity. The pseudo-absolute position solution uses a user-
-- provided, well-surveyed base station position (if available) and the RTK
-- solution in tandem.
module SwiftNav.SBP.Navigation where
import Control.Monad
import Control.Monad.Loops
import Data.Binary
import Data.Binary.Get
import Data.Binary.IEEE754
import Data.Binary.Put
import Data.ByteString
import Data.ByteString.Lazy hiding ( ByteString )
import Data.Int
import Data.Word
msgGpsTime :: Word16
msgGpsTime = 0x0100
-- | SBP class for message MSG_GPS_TIME (0x0100).
--
-- This message reports the GPS time, representing the time since the GPS epoch
-- began on midnight January 6, 1980 UTC. GPS time counts the weeks and seconds
-- of the week. The weeks begin at the Saturday/Sunday transition. GPS week 0
-- began at the beginning of the GPS time scale. Within each week number, the
-- GPS time of the week is between between 0 and 604800 seconds (=60*60*24*7).
-- Note that GPS time does not accumulate leap seconds, and as of now, has a
-- small offset from UTC. In a message stream, this message precedes a set of
-- other navigation messages referenced to the same time (but lacking the ns
-- field) and indicates a more precise time of these messages.
data MsgGpsTime = MsgGpsTime
{ msgGpsTimeWn :: Word16
-- ^ GPS week number
, msgGpsTimeTow :: Word32
-- ^ GPS time of week rounded to the nearest millisecond
, msgGpsTimeNs :: Int32
-- ^ Nanosecond residual of millisecond-rounded TOW (ranges from -500000 to
-- 500000)
, msgGpsTimeFlags :: Word8
-- ^ Status flags (reserved)
} deriving ( Show, Read, Eq )
instance Binary MsgGpsTime where
get = do
msgGpsTimeWn <- getWord16le
msgGpsTimeTow <- getWord32le
msgGpsTimeNs <- liftM fromIntegral getWord32le
msgGpsTimeFlags <- getWord8
return MsgGpsTime {..}
put MsgGpsTime {..} = do
putWord16le msgGpsTimeWn
putWord32le msgGpsTimeTow
putWord32le $ fromIntegral msgGpsTimeNs
putWord8 msgGpsTimeFlags
msgDops :: Word16
msgDops = 0x0206
-- | SBP class for message MSG_DOPS (0x0206).
--
-- This dilution of precision (DOP) message describes the effect of navigation
-- satellite geometry on positional measurement precision.
data MsgDops = MsgDops
{ msgDopsTow :: Word32
-- ^ GPS Time of Week
, msgDopsGdop :: Word16
-- ^ Geometric Dilution of Precision
, msgDopsPdop :: Word16
-- ^ Position Dilution of Precision
, msgDopsTdop :: Word16
-- ^ Time Dilution of Precision
, msgDopsHdop :: Word16
-- ^ Horizontal Dilution of Precision
, msgDopsVdop :: Word16
-- ^ Vertical Dilution of Precision
} deriving ( Show, Read, Eq )
instance Binary MsgDops where
get = do
msgDopsTow <- getWord32le
msgDopsGdop <- getWord16le
msgDopsPdop <- getWord16le
msgDopsTdop <- getWord16le
msgDopsHdop <- getWord16le
msgDopsVdop <- getWord16le
return MsgDops {..}
put MsgDops {..} = do
putWord32le msgDopsTow
putWord16le msgDopsGdop
putWord16le msgDopsPdop
putWord16le msgDopsTdop
putWord16le msgDopsHdop
putWord16le msgDopsVdop
msgPosEcef :: Word16
msgPosEcef = 0x0200
-- | SBP class for message MSG_POS_ECEF (0x0200).
--
-- The position solution message reports absolute Earth Centered Earth Fixed
-- (ECEF) coordinates and the status (single point vs pseudo-absolute RTK) of
-- the position solution. If the rover receiver knows the surveyed position of
-- the base station and has an RTK solution, this reports a pseudo-absolute
-- position solution using the base station position and the rover's RTK
-- baseline vector. The full GPS time is given by the preceding MSG_GPS_TIME
-- with the matching time-of-week (tow).
data MsgPosEcef = MsgPosEcef
{ msgPosEcefTow :: Word32
-- ^ GPS Time of Week
, msgPosEcefX :: Double
-- ^ ECEF X coordinate
, msgPosEcefY :: Double
-- ^ ECEF Y coordinate
, msgPosEcefZ :: Double
-- ^ ECEF Z coordinate
, msgPosEcefAccuracy :: Word16
-- ^ Position accuracy estimate (not implemented). Defaults to 0.
, msgPosEcefNSats :: Word8
-- ^ Number of satellites used in solution
, msgPosEcefFlags :: Word8
-- ^ Status flags
} deriving ( Show, Read, Eq )
instance Binary MsgPosEcef where
get = do
msgPosEcefTow <- getWord32le
msgPosEcefX <- getFloat64le
msgPosEcefY <- getFloat64le
msgPosEcefZ <- getFloat64le
msgPosEcefAccuracy <- getWord16le
msgPosEcefNSats <- getWord8
msgPosEcefFlags <- getWord8
return MsgPosEcef {..}
put MsgPosEcef {..} = do
putWord32le msgPosEcefTow
putFloat64le msgPosEcefX
putFloat64le msgPosEcefY
putFloat64le msgPosEcefZ
putWord16le msgPosEcefAccuracy
putWord8 msgPosEcefNSats
putWord8 msgPosEcefFlags
msgPosLlh :: Word16
msgPosLlh = 0x0201
-- | SBP class for message MSG_POS_LLH (0x0201).
--
-- This position solution message reports the absolute geodetic coordinates and
-- the status (single point vs pseudo-absolute RTK) of the position solution.
-- If the rover receiver knows the surveyed position of the base station and
-- has an RTK solution, this reports a pseudo-absolute position solution using
-- the base station position and the rover's RTK baseline vector. The full GPS
-- time is given by the preceding MSG_GPS_TIME with the matching time-of-week
-- (tow).
data MsgPosLlh = MsgPosLlh
{ msgPosLlhTow :: Word32
-- ^ GPS Time of Week
, msgPosLlhLat :: Double
-- ^ Latitude
, msgPosLlhLon :: Double
-- ^ Longitude
, msgPosLlhHeight :: Double
-- ^ Height
, msgPosLlhHAccuracy :: Word16
-- ^ Horizontal position accuracy estimate (not implemented). Defaults to 0.
, msgPosLlhVAccuracy :: Word16
-- ^ Vertical position accuracy estimate (not implemented). Defaults to 0.
, msgPosLlhNSats :: Word8
-- ^ Number of satellites used in solution.
, msgPosLlhFlags :: Word8
-- ^ Status flags
} deriving ( Show, Read, Eq )
instance Binary MsgPosLlh where
get = do
msgPosLlhTow <- getWord32le
msgPosLlhLat <- getFloat64le
msgPosLlhLon <- getFloat64le
msgPosLlhHeight <- getFloat64le
msgPosLlhHAccuracy <- getWord16le
msgPosLlhVAccuracy <- getWord16le
msgPosLlhNSats <- getWord8
msgPosLlhFlags <- getWord8
return MsgPosLlh {..}
put MsgPosLlh {..} = do
putWord32le msgPosLlhTow
putFloat64le msgPosLlhLat
putFloat64le msgPosLlhLon
putFloat64le msgPosLlhHeight
putWord16le msgPosLlhHAccuracy
putWord16le msgPosLlhVAccuracy
putWord8 msgPosLlhNSats
putWord8 msgPosLlhFlags
msgBaselineEcef :: Word16
msgBaselineEcef = 0x0202
-- | SBP class for message MSG_BASELINE_ECEF (0x0202).
--
-- This message reports the baseline solution in Earth Centered Earth Fixed
-- (ECEF) coordinates. This baseline is the relative vector distance from the
-- base station to the rover receiver. The full GPS time is given by the
-- preceding MSG_GPS_TIME with the matching time-of-week (tow).
data MsgBaselineEcef = MsgBaselineEcef
{ msgBaselineEcefTow :: Word32
-- ^ GPS Time of Week
, msgBaselineEcefX :: Int32
-- ^ Baseline ECEF X coordinate
, msgBaselineEcefY :: Int32
-- ^ Baseline ECEF Y coordinate
, msgBaselineEcefZ :: Int32
-- ^ Baseline ECEF Z coordinate
, msgBaselineEcefAccuracy :: Word16
-- ^ Position accuracy estimate (not implemented). Defaults to 0.
, msgBaselineEcefNSats :: Word8
-- ^ Number of satellites used in solution
, msgBaselineEcefFlags :: Word8
-- ^ Status flags
} deriving ( Show, Read, Eq )
instance Binary MsgBaselineEcef where
get = do
msgBaselineEcefTow <- getWord32le
msgBaselineEcefX <- liftM fromIntegral getWord32le
msgBaselineEcefY <- liftM fromIntegral getWord32le
msgBaselineEcefZ <- liftM fromIntegral getWord32le
msgBaselineEcefAccuracy <- getWord16le
msgBaselineEcefNSats <- getWord8
msgBaselineEcefFlags <- getWord8
return MsgBaselineEcef {..}
put MsgBaselineEcef {..} = do
putWord32le msgBaselineEcefTow
putWord32le $ fromIntegral msgBaselineEcefX
putWord32le $ fromIntegral msgBaselineEcefY
putWord32le $ fromIntegral msgBaselineEcefZ
putWord16le msgBaselineEcefAccuracy
putWord8 msgBaselineEcefNSats
putWord8 msgBaselineEcefFlags
msgBaselineNed :: Word16
msgBaselineNed = 0x0203
-- | SBP class for message MSG_BASELINE_NED (0x0203).
--
-- This message reports the baseline solution in North East Down (NED)
-- coordinates. This baseline is the relative vector distance from the base
-- station to the rover receiver, and NED coordinate system is defined at the
-- local tangent plane centered at the base station position. The full GPS
-- time is given by the preceding MSG_GPS_TIME with the matching time-of-week
-- (tow).
data MsgBaselineNed = MsgBaselineNed
{ msgBaselineNedTow :: Word32
-- ^ GPS Time of Week
, msgBaselineNedN :: Int32
-- ^ Baseline North coordinate
, msgBaselineNedE :: Int32
-- ^ Baseline East coordinate
, msgBaselineNedD :: Int32
-- ^ Baseline Down coordinate
, msgBaselineNedHAccuracy :: Word16
-- ^ Horizontal position accuracy estimate (not implemented). Defaults to 0.
, msgBaselineNedVAccuracy :: Word16
-- ^ Vertical position accuracy estimate (not implemented). Defaults to 0.
, msgBaselineNedNSats :: Word8
-- ^ Number of satellites used in solution
, msgBaselineNedFlags :: Word8
-- ^ Status flags
} deriving ( Show, Read, Eq )
instance Binary MsgBaselineNed where
get = do
msgBaselineNedTow <- getWord32le
msgBaselineNedN <- liftM fromIntegral getWord32le
msgBaselineNedE <- liftM fromIntegral getWord32le
msgBaselineNedD <- liftM fromIntegral getWord32le
msgBaselineNedHAccuracy <- getWord16le
msgBaselineNedVAccuracy <- getWord16le
msgBaselineNedNSats <- getWord8
msgBaselineNedFlags <- getWord8
return MsgBaselineNed {..}
put MsgBaselineNed {..} = do
putWord32le msgBaselineNedTow
putWord32le $ fromIntegral msgBaselineNedN
putWord32le $ fromIntegral msgBaselineNedE
putWord32le $ fromIntegral msgBaselineNedD
putWord16le msgBaselineNedHAccuracy
putWord16le msgBaselineNedVAccuracy
putWord8 msgBaselineNedNSats
putWord8 msgBaselineNedFlags
msgVelEcef :: Word16
msgVelEcef = 0x0204
-- | SBP class for message MSG_VEL_ECEF (0x0204).
--
-- This message reports the velocity in Earth Centered Earth Fixed (ECEF)
-- coordinates. The full GPS time is given by the preceding MSG_GPS_TIME with
-- the matching time-of-week (tow).
data MsgVelEcef = MsgVelEcef
{ msgVelEcefTow :: Word32
-- ^ GPS Time of Week
, msgVelEcefX :: Int32
-- ^ Velocity ECEF X coordinate
, msgVelEcefY :: Int32
-- ^ Velocity ECEF Y coordinate
, msgVelEcefZ :: Int32
-- ^ Velocity ECEF Z coordinate
, msgVelEcefAccuracy :: Word16
-- ^ Velocity accuracy estimate (not implemented). Defaults to 0.
, msgVelEcefNSats :: Word8
-- ^ Number of satellites used in solution
, msgVelEcefFlags :: Word8
-- ^ Status flags (reserved)
} deriving ( Show, Read, Eq )
instance Binary MsgVelEcef where
get = do
msgVelEcefTow <- getWord32le
msgVelEcefX <- liftM fromIntegral getWord32le
msgVelEcefY <- liftM fromIntegral getWord32le
msgVelEcefZ <- liftM fromIntegral getWord32le
msgVelEcefAccuracy <- getWord16le
msgVelEcefNSats <- getWord8
msgVelEcefFlags <- getWord8
return MsgVelEcef {..}
put MsgVelEcef {..} = do
putWord32le msgVelEcefTow
putWord32le $ fromIntegral msgVelEcefX
putWord32le $ fromIntegral msgVelEcefY
putWord32le $ fromIntegral msgVelEcefZ
putWord16le msgVelEcefAccuracy
putWord8 msgVelEcefNSats
putWord8 msgVelEcefFlags
msgVelNed :: Word16
msgVelNed = 0x0205
-- | SBP class for message MSG_VEL_NED (0x0205).
--
-- This message reports the velocity in local North East Down (NED)
-- coordinates. The full GPS time is given by the preceding MSG_GPS_TIME with
-- the matching time-of-week (tow).
data MsgVelNed = MsgVelNed
{ msgVelNedTow :: Word32
-- ^ GPS Time of Week
, msgVelNedN :: Int32
-- ^ Velocity North coordinate
, msgVelNedE :: Int32
-- ^ Velocity East coordinate
, msgVelNedD :: Int32
-- ^ Velocity Down coordinate
, msgVelNedHAccuracy :: Word16
-- ^ Horizontal velocity accuracy estimate (not implemented). Defaults to 0.
, msgVelNedVAccuracy :: Word16
-- ^ Vertical velocity accuracy estimate (not implemented). Defaults to 0.
, msgVelNedNSats :: Word8
-- ^ Number of satellites used in solution
, msgVelNedFlags :: Word8
-- ^ Status flags (reserved)
} deriving ( Show, Read, Eq )
instance Binary MsgVelNed where
get = do
msgVelNedTow <- getWord32le
msgVelNedN <- liftM fromIntegral getWord32le
msgVelNedE <- liftM fromIntegral getWord32le
msgVelNedD <- liftM fromIntegral getWord32le
msgVelNedHAccuracy <- getWord16le
msgVelNedVAccuracy <- getWord16le
msgVelNedNSats <- getWord8
msgVelNedFlags <- getWord8
return MsgVelNed {..}
put MsgVelNed {..} = do
putWord32le msgVelNedTow
putWord32le $ fromIntegral msgVelNedN
putWord32le $ fromIntegral msgVelNedE
putWord32le $ fromIntegral msgVelNedD
putWord16le msgVelNedHAccuracy
putWord16le msgVelNedVAccuracy
putWord8 msgVelNedNSats
putWord8 msgVelNedFlags