from navigator.epoch import from_rinex_files, Epoch
from pathlib import Path
from tests.common_fixtures import (
skydel_sim_obs_filepath,
skydel_sim_nav_filepath,
skyder_true_reciever_state_filepath,
)
from navigator.core import Triangulate, IterativeTriangulationInterface
import pandas as pd
import numpy as np
import pytest
def test_gps_triangulation_on_sim_dataset(
skydel_sim_obs_filepath,
skydel_sim_nav_filepath,
skyder_true_reciever_state_filepath,
):
"""Test GPS triangulation on simulated dataset.
Note:
The tropospheric and ionospheric models are not checked in this test.
Args:
skydel_sim_obs_filepath (str): Path to the simulated observation file.
skydel_sim_nav_filepath (str): Path to the simulated navigation file.
skyder_true_reciever_state_filepath (str): Path to the true receiver state file.
"""
# Spacing
N = 10
# Create a column mapper
column_mapper = {
Epoch.L1_CODE_ON: "CA",
Epoch.L2_CODE_ON: "CC",
Epoch.L1_PHASE_ON: "LA",
Epoch.L2_PHASE_ON: "LC",
}
# Create test epochs
epochs = list(
from_rinex_files(
skydel_sim_obs_filepath,
skydel_sim_nav_filepath,
column_mapper=column_mapper,
)
)
# Read the true receiver state
true_state = pd.read_csv(skyder_true_reciever_state_filepath, index_col=0)
position_colnames = ["ECEF X (m)", "ECEF Y (m)", "ECEF Z (m)"]
triangulate_pos_colnames = ["x", "y", "z"]
# Create Triangulate object
triangulator = Triangulate(
interface=IterativeTriangulationInterface(code_only=True)
)
# Triangulate on N spaced epochs
df = triangulator.triangulate_time_series(epoches=epochs[::10])
# Check that the norm of the difference between the true and estimated positions is less than 1 meter
error = np.linalg.norm(
df[triangulate_pos_colnames].values - true_state[position_colnames].values,
axis=1,
)
# Check that the error is less than 1cm
assert np.all(error < 0.01)
# Check that the clock bias is approximately zero
assert pytest.approx(df["cdt"].mean(), abs=0.01) == 0
# Assert the UREA is less than 0.001m
assert pytest.approx(df["UREA"].mean(), abs=0.001) == 0