Skip to content

Commit 945d2c8

Browse files
committed
residual updates
1 parent 1801106 commit 945d2c8

1 file changed

Lines changed: 31 additions & 13 deletions

File tree

gnss_lib_py/algorithms/fde.py

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ def fde_residual_old(navdata, max_faults, threshold,
371371
verbose=False, debug=False):
372372
"""Residual-based fault detection and exclusion.
373373
374+
Implemented based on paper from Parkinson [1]_.
375+
374376
Parameters
375377
----------
376378
navdata : gnss_lib_py.parsers.navdata.NavData
@@ -398,6 +400,12 @@ def fde_residual_old(navdata, max_faults, threshold,
398400
no fault was detected, and 2 indicates an unknown fault status
399401
usually due to lack of necessary columns or information.
400402
403+
References
404+
----------
405+
.. [1] Parkinson, Bradford W., and Penina Axelrad. "Autonomous GPS
406+
integrity monitoring using the pseudorange residual."
407+
Navigation 35.2 (1988): 255-274.
408+
401409
"""
402410

403411
fault_residual = []
@@ -427,18 +435,11 @@ def fde_residual_old(navdata, max_faults, threshold,
427435
navdata_subset.remove(cols=nan_idxs,inplace=True)
428436
original_indexes = np.delete(original_indexes, nan_idxs)
429437

430-
431-
# solve for residuals
432-
receiver_state = solve_wls(navdata_subset)
433-
solve_residuals(navdata_subset, receiver_state, inplace=True)
434-
# if len(navdata_subset) < 6:
435438
ri = []
436439
if len(navdata_subset) > 6:
437-
residuals = navdata_subset["residuals_m"].reshape(-1,1)
438440

439441
# test statistic
440-
r = np.sqrt(residuals.T.dot(residuals)[0,0] \
441-
/ (subset_length - 4) )
442+
r = _residual_detection_statistic(navdata_subset)
442443

443444
if verbose:
444445
print("residual test statistic:",r)
@@ -448,12 +449,15 @@ def fde_residual_old(navdata, max_faults, threshold,
448449
ri = set()
449450
r_subsets = []
450451
for ss in range(len(navdata_subset)):
451-
residual_subset = np.delete(residuals,ss,axis=0)
452-
r_subset = np.sqrt(residual_subset.T.dot(residual_subset)[0,0] \
453-
/ (len(residual_subset) - 4) )
452+
navdata_exclude = navdata_subset.remove(cols=[ss])
453+
r_subset = _residual_detection_statistic(navdata_exclude)
454+
454455
if verbose:
455456
r_subsets.append(r_subset)
456457
# adjusted threshold metric
458+
if verbose:
459+
print("r_subset/r:",r_subset/r,ss,"removed")
460+
# 1. chosen based on similarity to 8m/10m ratio from [1]_.
457461
if r_subset/r < 1.:
458462
ri.add(ss)
459463

@@ -462,8 +466,6 @@ def fde_residual_old(navdata, max_faults, threshold,
462466
print("NONE fail:")
463467
print("r: ",r)
464468
print("ri: ",ri)
465-
for rri, rrr in enumerate(residuals):
466-
print(rri, rrr, r_subsets[rri]/r)
467469
else:
468470
if verbose:
469471
print("threshold fail:")
@@ -492,6 +494,22 @@ def fde_residual_old(navdata, max_faults, threshold,
492494
return navdata, debug_info
493495
return navdata
494496

497+
def _residual_detection_statistic(navdata):
498+
"""Detection statistic for Residual-based fault detection.
499+
500+
"""
501+
# solve for residuals
502+
receiver_state = solve_wls(navdata)
503+
solve_residuals(navdata, receiver_state, inplace=True)
504+
# if len(navdata_subset) < 6:
505+
residuals = navdata["residuals_m"].reshape(-1,1)
506+
507+
# test statistic
508+
detection_statistic = np.sqrt(residuals.T.dot(residuals)[0,0] \
509+
/ (len(navdata) - 4) )
510+
511+
return detection_statistic
512+
495513
def fde_solution_separation_old(navdata, max_faults, threshold,
496514
verbose=False):
497515
"""Solution separation fault detection and exclusion.

0 commit comments

Comments
 (0)