mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2026-10-13 03:01:50 +00:00
Improve robustness against code outliers
This commit is contained in:
@@ -1981,12 +1981,16 @@ int ddres(rtk_t *rtk, const obsd_t *obs, const nav_t *nav, double dt, const doub
|
||||
if (opt->maxinno[f < nf ? 0 : 1] > 0.0 &&
|
||||
fabs(v[nv]) > opt->maxinno[f < nf ? 0 : 1] * threshadj)
|
||||
{
|
||||
/* charge the outlier only to the non-reference
|
||||
/* charge phase outliers only to the non-reference
|
||||
satellite (demo5): the reference is part of every
|
||||
pair and would otherwise reach the rejc-based bias
|
||||
reset from rejections it did not cause */
|
||||
rtk->ssat[sat[j] - 1].vsat[frq] = 0;
|
||||
rtk->ssat[sat[j] - 1].rejc[frq]++;
|
||||
reset from rejections it did not cause. Code
|
||||
outliers must not modify carrier-phase state */
|
||||
if (f < nf)
|
||||
{
|
||||
rtk->ssat[sat[j] - 1].vsat[frq] = 0;
|
||||
rtk->ssat[sat[j] - 1].rejc[frq]++;
|
||||
}
|
||||
errmsg(rtk, "outlier rejected (sat=%3d-%3d %s%d v=%.3f)\n",
|
||||
sat[i], sat[j], f < nf ? "L" : "P", f % nf + 1, v[nv]);
|
||||
continue;
|
||||
|
||||
@@ -1281,6 +1281,64 @@ TEST_F(RtklibFixedBaseTest, AFreshlyResetBiasIsAdmittedThroughTheWidenedInnovati
|
||||
}
|
||||
|
||||
|
||||
TEST_F(RtklibFixedBaseTest, CodeOutliersDoNotCorruptCarrierPhaseState)
|
||||
{
|
||||
using namespace rtklib_fixed_base_test_detail;
|
||||
const double base_position_geodetic[3] = {45.0 * D2R, 8.0 * D2R, 100.0};
|
||||
double base_position_ecef[3]{};
|
||||
pos2ecef(base_position_geodetic, base_position_ecef);
|
||||
const double baseline_enu_m[3] = {8.0, 4.0, 1.0};
|
||||
double baseline_ecef_m[3]{};
|
||||
enu2ecef(base_position_geodetic, baseline_enu_m, baseline_ecef_m);
|
||||
const double rover_position_ecef[3] = {
|
||||
base_position_ecef[0] + baseline_ecef_m[0],
|
||||
base_position_ecef[1] + baseline_ecef_m[1],
|
||||
base_position_ecef[2] + baseline_ecef_m[2]};
|
||||
|
||||
prcopt_t options = fixed_base_options();
|
||||
options.modear = ARMODE_OFF;
|
||||
options.maxout = 50;
|
||||
auto solver = make_solver_with_options(options);
|
||||
const std::vector<unsigned int> satellites = select_relative_satellites(
|
||||
base_position_ecef, rover_position_ecef);
|
||||
ASSERT_GE(satellites.size(), 6U);
|
||||
|
||||
/* Corrupt only an L2 pseudorange after the filter has converged. The L2
|
||||
carrier and the L1 code used by the single-point seed remain clean. */
|
||||
const unsigned int corrupted_prn = satellites.back();
|
||||
constexpr int OUTLIER_EPOCH = 6;
|
||||
constexpr double CODE_ERROR_M = 300.0;
|
||||
|
||||
for (int epoch_index = 0; epoch_index <= OUTLIER_EPOCH; ++epoch_index)
|
||||
{
|
||||
Synthetic_Relative_Epoch epoch = make_relative_epoch(
|
||||
*solver, epoch_index, base_position_ecef, rover_position_ecef, satellites);
|
||||
if (epoch_index == OUTLIER_EPOCH)
|
||||
{
|
||||
const auto observation = epoch.rover_observations.find(
|
||||
static_cast<int>(corrupted_prn * 2U + 1U));
|
||||
ASSERT_NE(epoch.rover_observations.end(), observation);
|
||||
observation->second.Pseudorange_m += CODE_ERROR_M;
|
||||
}
|
||||
|
||||
SCOPED_TRACE(::testing::Message() << "epoch=" << epoch_index);
|
||||
ASSERT_TRUE(solve(*solver, epoch.rover_observations, &epoch.base_snapshot));
|
||||
}
|
||||
|
||||
bool rejected_code_row = false;
|
||||
for (const unsigned int prn : satellites)
|
||||
{
|
||||
const auto& state = solver->pvt_ssat[prn - 1U];
|
||||
rejected_code_row = rejected_code_row ||
|
||||
std::fabs(state.resp[1]) > options.maxinno[1];
|
||||
EXPECT_EQ(0U, state.rejc[1]);
|
||||
EXPECT_NE(0U, state.vsat[1]);
|
||||
EXPECT_EQ(0U, state.outc[1]);
|
||||
}
|
||||
EXPECT_TRUE(rejected_code_row);
|
||||
}
|
||||
|
||||
|
||||
TEST_F(RtklibFixedBaseTest, ATransientOutlierDoesNotChargeTheReferenceSatellite)
|
||||
{
|
||||
using namespace rtklib_fixed_base_test_detail;
|
||||
|
||||
Reference in New Issue
Block a user