-
Notifications
You must be signed in to change notification settings - Fork 13.6k
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: 1376 byte (0.07 %)]
px4_fmu-v6x [Total VM Diff: 1368 byte (0.07 %)]
Updated: 2024-12-13T13:28:06 |
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
z = sf.Symbol("z") | ||
dist_bottom = sf.Symbol("dist_bottom") | ||
terrain = z - dist_bottom | ||
state = sf.V2.symbolic("state") |
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 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; |
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.
_A
is just the identity matrix, right? So you could just do _P += Q
and not store _A as a member variable
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.
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; |
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.
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}; |
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.
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); |
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 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
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.Screenshots will follow