192 lines
5.6 KiB
C
192 lines
5.6 KiB
C
#include "gps/gps_tracking_measurement.h"
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#define TEST_SATELLITES 6u
|
|
|
|
static bool close_to(double actual, double expected, double tolerance)
|
|
{
|
|
return fabs(actual - expected) <= tolerance;
|
|
}
|
|
|
|
static uint64_t cn0_wbp_for_target(
|
|
int32_t sum_i,
|
|
int32_t sum_q,
|
|
unsigned int sample_count,
|
|
double cn0_dbhz)
|
|
{
|
|
double cn0_linear = pow(10.0, cn0_dbhz / 10.0);
|
|
double scaled = cn0_linear / 1000.0;
|
|
double ratio =
|
|
(scaled * (double)sample_count + 1.0) / (scaled + 1.0);
|
|
double narrowband =
|
|
(double)sum_i * (double)sum_i +
|
|
(double)sum_q * (double)sum_q;
|
|
return (uint64_t)llround(narrowband / ratio);
|
|
}
|
|
|
|
static void test_cn0_and_mailbox_decode(void)
|
|
{
|
|
gps_trck_t registers;
|
|
memset(®isters, 0, sizeof(registers));
|
|
|
|
const int32_t sum_i = 20000;
|
|
const int32_t sum_q = 1000;
|
|
const uint64_t wbp =
|
|
cn0_wbp_for_target(sum_i, sum_q, 20u, 45.0);
|
|
const int32_t carrier_q7 =
|
|
(int32_t)llround((GPS_TRCK_IF_CENTER_HZ + 2500.0) *
|
|
GPS_TRCK_CARRIER_Q7_SCALE);
|
|
|
|
registers.PRN_NUMBER = 7u;
|
|
registers.MEASUREMENT_META =
|
|
(GPS_TRCK_MEAS_META_VERSION <<
|
|
GPS_TRCK_MEAS_META_VERSION_SHIFT) |
|
|
(20u << GPS_TRCK_MEAS_META_COUNT_SHIFT) |
|
|
(1u << GPS_TRCK_MEAS_META_VALID_POS) |
|
|
(1u << GPS_TRCK_MEAS_META_NAV_BIT_POS) |
|
|
(1u << GPS_TRCK_MEAS_META_LOCK_POS);
|
|
registers.MEASUREMENT_SEQUENCE = 0x1234u;
|
|
registers.MEASUREMENT_CARRIER_Q7 = carrier_q7;
|
|
registers.MEASUREMENT_ABS_SAMPLE = 0x89abcdefu;
|
|
registers.MEASUREMENT_REM_CODE_PHASE = 555u;
|
|
registers.MEASUREMENT_SUM_I = sum_i;
|
|
registers.MEASUREMENT_SUM_Q = sum_q;
|
|
registers.MEASUREMENT_WBP_LO = (uint32_t)wbp;
|
|
registers.MEASUREMENT_WBP_HI = (uint32_t)(wbp >> 32);
|
|
|
|
gps_tracking_measurement_t measurement;
|
|
assert(gps_tracking_measurement_read(®isters, &measurement));
|
|
assert(measurement.valid);
|
|
assert(measurement.locked);
|
|
assert(measurement.nav_bit);
|
|
assert(measurement.prn == 7u);
|
|
assert(measurement.sequence == 0x1234u);
|
|
assert(measurement.absolute_sample == 0x89abcdefu);
|
|
assert(measurement.remaining_code_phase == 555u);
|
|
assert(measurement.cn0_sample_count == 20u);
|
|
assert(measurement.cn0_wbp == wbp);
|
|
assert(close_to(measurement.cn0_dbhz, 45.0, 0.01));
|
|
assert(close_to(measurement.doppler_hz, 2500.0, 1.0 / 128.0));
|
|
|
|
const double expected_range_rate =
|
|
-2500.0 * ((double)SPEED_OF_LIGHT / GPS_L1_CARRIER_HZ);
|
|
assert(close_to(
|
|
measurement.pseudorange_rate_mps,
|
|
expected_range_rate,
|
|
1.0e-9));
|
|
|
|
registers.MEASUREMENT_META &=
|
|
~(1u << GPS_TRCK_MEAS_META_LOCK_POS);
|
|
assert(!gps_tracking_measurement_read(®isters, &measurement));
|
|
assert(!measurement.valid);
|
|
}
|
|
|
|
static void test_velocity_wls(void)
|
|
{
|
|
const double receiver_position[3] = {6378137.0, 0.0, 0.0};
|
|
const double directions[TEST_SATELLITES][3] = {
|
|
{ 1.0, 0.0, 0.0},
|
|
{ 0.0, 1.0, 0.0},
|
|
{ 0.0, 0.0, 1.0},
|
|
{-0.5773502691896258, 0.5773502691896258, 0.5773502691896258},
|
|
{ 0.7071067811865475, -0.7071067811865475, 0.0},
|
|
{ 0.4082482904638631, 0.4082482904638631, -0.8164965809277261}
|
|
};
|
|
const double satellite_velocities[TEST_SATELLITES][3] = {
|
|
{ 0.0, 2700.0, 100.0},
|
|
{-900.0, 0.0, 2500.0},
|
|
{1200.0, -2100.0, 0.0},
|
|
{1800.0, 400.0, -800.0},
|
|
{-500.0, 1900.0, 600.0},
|
|
{ 700.0, -1200.0, 2200.0}
|
|
};
|
|
const double satellite_clock_drift[TEST_SATELLITES] = {
|
|
1.0e-11, -2.0e-11, 0.5e-11, 1.5e-11, -0.7e-11, 2.2e-11
|
|
};
|
|
const double expected_velocity[3] = {12.0, -4.0, 1.5};
|
|
const double expected_clock_drift_mps = 18.0;
|
|
|
|
double satellite_positions[TEST_SATELLITES][3];
|
|
gps_tracking_measurement_t measurements[TEST_SATELLITES];
|
|
memset(measurements, 0, sizeof(measurements));
|
|
for(unsigned int satellite = 0u;
|
|
satellite < TEST_SATELLITES;
|
|
satellite++)
|
|
{
|
|
double los_satellite_velocity = 0.0;
|
|
double los_receiver_velocity = 0.0;
|
|
for(unsigned int component = 0u; component < 3u; component++)
|
|
{
|
|
satellite_positions[satellite][component] =
|
|
receiver_position[component] +
|
|
directions[satellite][component] * 21000000.0;
|
|
los_satellite_velocity +=
|
|
directions[satellite][component] *
|
|
satellite_velocities[satellite][component];
|
|
los_receiver_velocity +=
|
|
directions[satellite][component] *
|
|
expected_velocity[component];
|
|
}
|
|
measurements[satellite].valid = true;
|
|
measurements[satellite].locked = true;
|
|
measurements[satellite].cn0_dbhz = 42.0 + (double)satellite;
|
|
measurements[satellite].pseudorange_rate_mps =
|
|
los_satellite_velocity -
|
|
los_receiver_velocity +
|
|
expected_clock_drift_mps -
|
|
(double)SPEED_OF_LIGHT *
|
|
satellite_clock_drift[satellite];
|
|
}
|
|
|
|
double solved_velocity[3];
|
|
double solved_velocity_covariance[3][3];
|
|
double solved_clock_drift;
|
|
double residual_rms;
|
|
assert(gps_tracking_velocity_wls(
|
|
receiver_position,
|
|
satellite_positions,
|
|
satellite_velocities,
|
|
satellite_clock_drift,
|
|
measurements,
|
|
TEST_SATELLITES,
|
|
solved_velocity,
|
|
solved_velocity_covariance,
|
|
&solved_clock_drift,
|
|
&residual_rms));
|
|
|
|
for(unsigned int component = 0u; component < 3u; component++)
|
|
{
|
|
assert(close_to(
|
|
solved_velocity[component],
|
|
expected_velocity[component],
|
|
1.0e-9));
|
|
}
|
|
assert(close_to(
|
|
solved_clock_drift,
|
|
expected_clock_drift_mps,
|
|
1.0e-9));
|
|
assert(residual_rms < 1.0e-9);
|
|
for(unsigned int component = 0u; component < 3u; component++)
|
|
{
|
|
assert(isfinite(
|
|
solved_velocity_covariance[component][component]));
|
|
assert(solved_velocity_covariance[component][component] > 0.0);
|
|
}
|
|
assert(close_to(
|
|
solved_velocity_covariance[0][1],
|
|
solved_velocity_covariance[1][0],
|
|
1.0e-12));
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
test_cn0_and_mailbox_decode();
|
|
test_velocity_wls();
|
|
puts("test_gps_tracking_measurement PASS");
|
|
return 0;
|
|
}
|