@@ -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+
495513def fde_solution_separation_old (navdata , max_faults , threshold ,
496514 verbose = False ):
497515 """Solution separation fault detection and exclusion.
0 commit comments