-
Notifications
You must be signed in to change notification settings - Fork 13.7k
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
base: main
Are you sure you want to change the base?
Conversation
🔎 FLASH Analysispx4_fmu-v5x [Total VM Diff: 768 byte (0.04 %)]
px4_fmu-v6x [Total VM Diff: 768 byte (0.04 %)]
Updated: 2025-01-10T10:01:38 |
There was a problem hiding this 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
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.hpp
Outdated
Show resolved
Hide resolved
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
499efdc
to
f7052d6
Compare
11655eb
to
9f42b6e
Compare
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
_time_last_horizontal_motion = time_us; | ||
} | ||
float p[4] = {z_var, 0.f, 0.f, z_var + dist_bottom_var}; | ||
_P = Matrix<float, RangeFilter::size, RangeFilter::size>(p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_P = Matrix<float, RangeFilter::size, RangeFilter::size>(p); | |
_P = SquareMatrix<float, RangeFilter::size>(p); |
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
src/modules/ekf2/EKF/aid_sources/range_finder/range_finder_consistency_check.cpp
Outdated
Show resolved
Hide resolved
@dakejahl Does this help our height issues? |
9f42b6e
to
42ea74c
Compare
This was a quick indoor flight in manual mode. https://review.px4.io/plot_app?log=e3d3cf76-563d-4a23-9308-d37cbdcd34c3 Vs current main https://review.px4.io/plot_app?log=6d902213-02ef-4ff8-8474-d341bfcc7bd9 |
@AlexKlimaj Your vertical velocity estimate seems to be off quite a lot. Can you increase the bias noise on the acc so the bias will converge a bit quicker? The new filter uses the velocity estimate of the EKF to verify if the measurement is correct or not but when the EKF estimate is off and has a low uncertainty then it will discard the range measurements. |
42ea74c
to
e488ddb
Compare
float p[4] = {z_var, z_var, z_var, z_var + dist_bottom_var}; | ||
_P = SquareMatrix<float, RangeFilter::size>(p); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
float p[4] = {z_var, z_var, z_var, z_var + dist_bottom_var}; | |
_P = SquareMatrix<float, RangeFilter::size>(p); | |
_P(RangeFilter::z.idx, RangeFilter::z.idx) = z_var; | |
_P(RangeFilter::z.idx, RangeFilter::terrain.idx) = z_var; | |
_P(RangeFilter::terrain.idx, RangeFilter::z.idx) = _P(RangeFilter::z.idx, RangeFilter::terrain.idx); | |
_P(RangeFilter::terrain.idx, RangeFilter::terrain.idx) = z_var + dist_bottom_var; |
Either that with a description (we don't want to rely on a specific state order) on how you get those values, simply do a reset to 0 followed by a forced fusion (with modified K).
@@ -725,6 +725,20 @@ def compute_gravity_z_innov_var_and_h( | |||
|
|||
return (innov_var, H.T) | |||
|
|||
def range_validation_filter() -> sf.Matrix: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def range_validation_filter() -> sf.Matrix: | |
def range_validation_filter_h() -> sf.Matrix: |
resetTerrainToRng(aid_src); | ||
resetAidSourceStatusZeroInnovation(aid_src); | ||
} | ||
} | ||
|
||
} else { | ||
ECL_WARN("stopping %s fusion, continuing conditions failing", HGT_SRC_NAME); | ||
ECL_WARN("stoppPing %s fusion, continuing conditions failing", HGT_SRC_NAME); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pong
_x(RangeFilter::terrain.idx) = z - dist_bottom; | ||
_initialized = true; | ||
_state = KinematicState::UNKNOWN; | ||
_test_ratio_lpf.reset(2.f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why 2?
const float var = 2.f * dist_bottom_var / (dt * dt); | ||
_innov_var = var + vz_var; | ||
_x(RangeFilter::z.idx) -= dt * vz; | ||
_P(0, 0) += dt * dt * vz_var + 0.001f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RangeFilter::z.idx
...
if ((time_us - _time_last_horizontal_motion) > _signed_test_ratio_tau) { | ||
_is_kinematically_consistent = false; | ||
_time_last_inconsistent_us = time_us; | ||
Vector2f PH = _P.row(i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only works for direct states observations, you can't use this for the range finder update.
_state = KinematicState::UNKNOWN; | ||
_test_ratio_lpf.reset(2.f); | ||
_t_since_first_sample = 0.f; | ||
_test_ratio_lpf.setAlpha(0.2f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can now set the time constant as a parameter in the constructor and specify the dt
in the update
function to automatically compute the correct alpha parameter. See here for example.
dist_bottom = state["z"] - state["terrain"] | ||
|
||
H = sf.M22() | ||
H[0, :] = sf.V1(state["z"]).jacobian(state.to_storage(), tangent_space=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a direct state observation, so you don't even need to generate that observation matrix if you split the fusion process completely.
_sensor_simulator._baro.setData(_sensor_simulator._baro.getData() + baro_increment); | ||
_sensor_simulator.runSeconds(60); | ||
const float baro_initial = _sensor_simulator._baro.getData(); | ||
const float baro_inc = 0.2f; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
baro_inc
and baro_increment
You could call it baro_slew_rate
and multiply it with the dt of 3 seconds you have in the loop
|
||
const float corr_terrain_abias_z = P(State::accel_bias.idx + 2, | ||
State::terrain.idx) / sqrtf(_ekf->getAccelBiasVariance()(2) * var_terrain); | ||
EXPECT_NEAR(corr_terrain_abias_z, -0.4f, 0.03f); | ||
EXPECT_TRUE(corr_terrain_abias_z < -0.1f); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea. Could you make sure the norm of the correlation never exceeds 1?
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
andunknown
. 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.new:
old: