jord-2.0.0.0: test/Data/Geo/Jord/LocalSpec.hs
module Data.Geo.Jord.LocalSpec
( spec
) where
import Test.Hspec
import qualified Data.Geo.Jord.Angle as Angle
import qualified Data.Geo.Jord.Geodetic as Geodetic
import qualified Data.Geo.Jord.Length as Length
import Data.Geo.Jord.Local (Ned(..))
import qualified Data.Geo.Jord.Local as Local
import qualified Data.Geo.Jord.Math3d as Math3d
import Data.Geo.Jord.Models (WGS84(..))
spec :: Spec
spec = do
describe "Ellipsoidal earth model" $ do
describe "destination" $ do
it "return the given position if NED norm = 0" $ do
let p0 = Geodetic.latLongHeightPos 53.320556 (-1.729722) Length.zero WGS84
let d = Ned Length.zero Length.zero Length.zero
Local.destinationN p0 d `shouldBe` p0
it "computes the destination position from p0 and NED" $ do
let p0 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
let d = Local.nedMetres (-86126) (-78900) 1069
Local.destinationN p0 d `shouldBe`
Geodetic.latLongHeightPos
48.886668961666665
2.3747212533333335
(Length.metres 0.198937)
WGS84
it "computes the destination position from p0 and vector in Frame B" $ do
let p0 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
let y = Angle.decimalDegrees 10 -- yaw
let r = Angle.decimalDegrees 20 -- roll
let p = Angle.decimalDegrees 30 -- pitch
let d = Local.deltaMetres 3000 2000 100
Local.destination p0 (Local.frameB y r p) d `shouldBe`
Geodetic.latLongHeightPos
49.69180157805555
3.4812670616666668
(Length.metres 6.007735)
WGS84
describe "nedBetween" $ do
it "computes NED between surface positions" $ do
let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 Length.zero WGS84
let d = Local.nedBetween p1 p2
d `shouldBe` Local.nedMetres (-86125.880549) (-78900.087818) 1069.19844
it "computes NED between positions" $ do
let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 (Length.metres 12000) WGS84
let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 (Length.metres 15000) WGS84
let d = Local.nedBetween p1 p2
d `shouldBe` Local.nedMetres (-86328.623924) (-79085.290891) (-1928.287847)
describe "deltaBetween" $
it "computes delta between positions in frame L" $ do
let p1 = Geodetic.latLongHeightPos 1 2 (Length.metres (-3)) WGS84
let p2 = Geodetic.latLongHeightPos 4 5 (Length.metres (-6)) WGS84
let w = Angle.decimalDegrees 5 -- wander azimuth
let d = Local.deltaBetween p1 p2 (Local.frameL w)
d `shouldBe` Local.deltaMetres 359490.578214 302818.522536 17404.271362
describe "deltaBetween and destination consistency" $
it "computes targetN p1 (nedBetween p1 p2) = p2" $ do
let p1 = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
let p2 = Geodetic.latLongHeightPos 48.88667 2.37472 Length.zero WGS84
Local.destinationN p1 (Local.nedBetween p1 p2) `shouldBe` p2
describe "rotation matrix to/from earth-fixed frame" $ do
it "computes rEN (frame N to earth-fixed frame)" $ do
let p = Geodetic.latLongHeightPos 0.0 0.0 Length.zero WGS84
let f = Local.frameN p
Local.rEF f `shouldBe`
[Math3d.vec3 0.0 0.0 (-1.0), Math3d.vec3 0.0 1.0 0.0, Math3d.vec3 1.0 0.0 0.0]
it "computes rEB (frame B to earth-fixed frame)" $ do
let p = Geodetic.latLongHeightPos 49.66618 3.45063 Length.zero WGS84
let f =
Local.frameB
(Angle.decimalDegrees 10)
(Angle.decimalDegrees 20)
(Angle.decimalDegrees 30)
p
Local.rEF f `shouldBe`
[ Math3d.vec3
(-0.49300713580470057)
(-0.37038991706707025)
(-0.7872453705044535)
, Math3d.vec3 0.1337450488624887 0.8618333991596926 (-0.4892396692804258)
, Math3d.vec3 0.8596837941652826 (-0.3464888186188679) (-0.375352198104241)
]
describe "North, East, Down delta" $ do
describe "slantRange" $
it "computes the slant range of a NED vector" $
Local.slantRange (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
Length.metres 116807.707952
describe "bearing" $
it "computes the bearing of a NED vector" $
Local.bearing (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
Angle.decimalDegrees 222.49278897666667
describe "elevation" $
it "computes the elevation of a NED vector from horizontal" $
Local.elevation (Local.nedMetres (-86126) (-78900) 1069) `shouldBe`
Angle.decimalDegrees (-0.5243664513888889)