Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New filter for distance sensor validation #24106

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

haumarco
Copy link
Contributor

Solved Problem

The distance sensor is being fused or used to reset the terrain state, even though its measurements do not accurately represent the distance to the ground due to obstructions caused by rain, snow, fog etc.

Solution

Now the distance sensor can be in 3 different states based on the lpf test ratio of a simple kalman filter: consistent, inconsistent and unknown. A terrain reset can only happen when the state is consistent. The sensor will be used for normal fusion in both consistent and inconsistent states. Together with the already existing fog detector, the robustness against sensor blockage/failure is increased.

Screenshots will follow

@haumarco haumarco requested a review from bresch December 13, 2024 13:22
Copy link

🔎 FLASH Analysis

px4_fmu-v5x [Total VM Diff: 1376 byte (0.07 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.1% +1.34Ki  +0.1% +1.34Ki    .text
  +0.8% +1.30Ki  +0.8% +1.30Ki    src/modules/ekf2/modules__ekf2_unity.cpp
  +0.0%     +21  +0.0%     +21    [section .text]
  +0.0%     +16  +0.0%     +16    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +0.2%      +3  +0.2%      +3    ../../src/systemcmds/ver/ver.cpp
+0.0%     +82  [ = ]       0    .debug_abbrev
   +11%     +56  [ = ]       0    ../../src/lib/version/version.c
  +0.5%     +26  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.0%     +44  [ = ]       0    .debug_frame
+0.0% +12.6Ki  [ = ]       0    .debug_info
  -0.2%      -4  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +29  [ = ]       0    ../../src/modules/commander/HealthAndArmingChecks/checks/estimatorCheck.cpp
  +0.0%     +13  [ = ]       0    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +0.1%     +13  [ = ]       0    msg/topics_sources/estimator_status_flags.cpp
  +0.0%      +9  [ = ]       0    msg/topics_sources/uORBMessageFieldsGenerated.cpp
  +1.3% +12.6Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.1% +5.67Ki  [ = ]       0    .debug_line
  -1.3%     -25  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +27  [ = ]       0    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +1.6% +5.66Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
  +0.4%      +5  [ = ]       0    task/task_cancelpt.c
+0.3% +14.7Ki  [ = ]       0    .debug_loc
  -0.0%     -15  [ = ]       0    ../../src/modules/commander/Commander.cpp
  +0.1%    +201  [ = ]       0    [section .debug_loc]
  +1.9% +14.5Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.4% +5.17Ki  [ = ]       0    .debug_ranges
  -2.6%      -8  [ = ]       0    ../../src/lib/version/version.c
  +0.1%     +64  [ = ]       0    [section .debug_ranges]
  +2.4% +5.12Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
  +3.1%      +2  [ = ]       0    task/task_cancelpt.c
+0.0%    +444  [ = ]       0    .debug_str
  +2.2%      +8  [ = ]       0    ../../platforms/common/pab_manifest.c
 -14.6%    -287  [ = ]       0    ../../src/lib/battery/battery.cpp
  -1.0%     -60  [ = ]       0    ../../src/modules/ekf2/EKF/yaw_estimator/EKFGSF_yaw.cpp
 -89.6% -2.25Ki  [ = ]       0    ../../src/modules/landing_target_estimator/KalmanFilter.cpp
  -7.8%     -33  [ = ]       0    ../../src/modules/landing_target_estimator/LandingTargetEstimator.cpp
  -0.0%      -1  [ = ]       0    ../../src/modules/landing_target_estimator/landing_target_estimator_main.cpp
  -0.1%     -16  [ = ]       0    ../../src/modules/mc_hover_thrust_estimator/MulticopterHoverThrustEstimator.cpp
  +1.0% +3.06Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-1.0%      -2  [ = ]       0    .shstrtab
+0.0%     +42  [ = ]       0    .strtab
  -8.1%     -32  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +32  [ = ]       0    [section .strtab]
  +0.3%     +42  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-0.0%     -32  [ = ]       0    .symtab
  -7.0%     -64  [ = ]       0    ../../src/lib/version/version.c
  +0.3%     +16  [ = ]       0    ../../src/modules/fw_pos_control/FixedwingPositionControl.cpp
  +0.1%     +48  [ = ]       0    [section .symtab]
  -0.2%     -32  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-7.9% -1.34Ki  [ = ]       0    [Unmapped]
+0.1% +38.8Ki  +0.1% +1.34Ki    TOTAL

px4_fmu-v6x [Total VM Diff: 1368 byte (0.07 %)]
    FILE SIZE        VM SIZE    
--------------  -------------- 
+0.1% +1.34Ki  +0.1% +1.34Ki    .text
  +0.8% +1.30Ki  +0.8% +1.30Ki    src/modules/ekf2/modules__ekf2_unity.cpp
  +0.0%     +16  +0.0%     +16    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +0.0%     +13  +0.0%     +13    [section .text]
  +0.2%      +3  +0.2%      +3    ../../src/systemcmds/ver/ver.cpp
+0.0%     +82  [ = ]       0    .debug_abbrev
   +11%     +56  [ = ]       0    ../../src/lib/version/version.c
  +0.5%     +26  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.0%     +44  [ = ]       0    .debug_frame
+0.0% +12.6Ki  [ = ]       0    .debug_info
  -0.2%      -4  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +29  [ = ]       0    ../../src/modules/commander/HealthAndArmingChecks/checks/estimatorCheck.cpp
  +0.0%     +13  [ = ]       0    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +0.1%     +13  [ = ]       0    msg/topics_sources/estimator_status_flags.cpp
  +0.0%      +9  [ = ]       0    msg/topics_sources/uORBMessageFieldsGenerated.cpp
  +1.3% +12.6Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.1% +5.66Ki  [ = ]       0    .debug_line
  -1.3%     -25  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +27  [ = ]       0    ../../src/modules/uxrce_dds_client/uxrce_dds_client.cpp
  +1.6% +5.66Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
  -0.3%      -3  [ = ]       0    task/task_cancelpt.c
+0.3% +14.9Ki  [ = ]       0    .debug_loc
  +0.1%    +205  [ = ]       0    [section .debug_loc]
  +2.0% +14.7Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
+0.4% +5.17Ki  [ = ]       0    .debug_ranges
  -2.6%      -8  [ = ]       0    ../../src/lib/version/version.c
  +0.1%     +64  [ = ]       0    [section .debug_ranges]
  +2.4% +5.12Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
  +1.5%      +1  [ = ]       0    task/task_cancelpt.c
+0.0%    +454  [ = ]       0    .debug_str
  +2.2%      +8  [ = ]       0    ../../platforms/common/pab_manifest.c
 -14.6%    -287  [ = ]       0    ../../src/lib/battery/battery.cpp
  -1.0%     -60  [ = ]       0    ../../src/modules/ekf2/EKF/yaw_estimator/EKFGSF_yaw.cpp
 -89.6% -2.25Ki  [ = ]       0    ../../src/modules/landing_target_estimator/KalmanFilter.cpp
  -7.8%     -33  [ = ]       0    ../../src/modules/landing_target_estimator/LandingTargetEstimator.cpp
  -0.1%     -16  [ = ]       0    ../../src/modules/mc_hover_thrust_estimator/MulticopterHoverThrustEstimator.cpp
  +1.0% +3.07Ki  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-0.9%      -2  [ = ]       0    .shstrtab
+0.0%     +42  [ = ]       0    .strtab
  -8.1%     -32  [ = ]       0    ../../src/lib/version/version.c
  +0.0%     +32  [ = ]       0    [section .strtab]
  +0.3%     +42  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-0.0%     -32  [ = ]       0    .symtab
  -7.0%     -64  [ = ]       0    ../../src/lib/version/version.c
  +0.3%     +16  [ = ]       0    ../../src/modules/fw_pos_control/FixedwingPositionControl.cpp
  +0.1%     +48  [ = ]       0    [section .symtab]
  -0.2%     -32  [ = ]       0    src/modules/ekf2/modules__ekf2_unity.cpp
-1.8% -1.34Ki  [ = ]       0    [Unmapped]
+0.1% +38.9Ki  +0.1% +1.34Ki    TOTAL

Updated: 2024-12-13T13:28:06

Copy link
Member

@bresch bresch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if using sequential fusion would actually give nicer code in the end so you wouldn't need to build all those 2x2 matrices

z = sf.Symbol("z")
dist_bottom = sf.Symbol("dist_bottom")
terrain = z - dist_bottom
state = sf.V2.symbolic("state")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can define the states in a Values structure like here:

State = Values(
quat_nominal = sf.Rot3(),
vel = sf.V3(),
pos = sf.V3(),
gyro_bias = sf.V3(),
accel_bias = sf.V3(),
mag_I = sf.V3(),
mag_B = sf.V3(),
wind_vel = sf.V2(),
terrain = sf.V1()
)

You can also pass a Values structure as an argument of jacobian


updateConsistency(vz, time_us);
_x(RangeFilter::z.idx) += dt * vz;
_P = _A * _P * _A.transpose() + Q;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_A is just the identity matrix, right? So you could just do _P += Q and not store _A as a member variable

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or even directly apply the noise to P the diagonal elements of P instead of first setting them in Q fillowed by a matrix addition. e.g.: _P(RangeFilter::terrain.idx, RangeFilter::terrain.idx) = terrain_process_noise;

// Variance of the time derivative of a random variable: var(dz/dt) = 2*var(z) / dt^2
const float var = 2.f * dist_bottom_var / (dt * dt);
_innov_var = var + vz_var;
_R(RangeFilter::z.idx, RangeFilter::z.idx) = z_var;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably no need to store _R as a member variable is you anyways override it at every iteration

float _gate{1.f};
int _sample_count{0};
KinematicState _state{KinematicState::UNKNOWN};
int _min_nr_of_samples{0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of computing how many samples are required and counting the number of samples you could simply accumulate the dt until it reaches the desired period (e.g.> 1s in your case).

_P = 0.5f * (_P + _P.transpose()); // Ensure symmetry
_innov = y(RangeFilter::terrain.idx);
_innov_var = S(RangeFilter::terrain.idx, RangeFilter::terrain.idx);
_test_ratio_lpf.update(test_ratio);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should really use a "signed test raio lpf" here as the test ratio is always positive and the average of the test ratio of a gaussian white noise is >0 while the average of the signed test ratio would be 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants