Skip to content

Commit 7b816df

Browse files
committed
Improve ball filter stability
1 parent 6905bc8 commit 7b816df

4 files changed

Lines changed: 89 additions & 5 deletions

File tree

crates/nodes/ball_filter/src/hypothesis.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl BallHypothesis {
8989
moving_process_noise,
9090
);
9191

92-
let velocity_covariance = moving.covariance.fixed_view::<2, 2>(0, 0);
92+
let velocity_covariance = moving.covariance.fixed_view::<2, 2>(2, 2);
9393
let velocity = nalgebra::vector![moving.mean.z, moving.mean.w];
9494

9595
let exponent = -velocity.dot(
@@ -152,3 +152,33 @@ impl BallHypothesis {
152152
};
153153
}
154154
}
155+
156+
#[cfg(test)]
157+
mod tests {
158+
use super::*;
159+
160+
#[test]
161+
fn predict_keeps_precise_non_zero_velocity_moving() {
162+
let mut hypothesis = BallHypothesis {
163+
mode: BallMode::Moving(MultivariateNormalDistribution {
164+
mean: nalgebra::vector![0.0, 0.0, 0.1, 0.0],
165+
covariance: Matrix4::from_diagonal(&nalgebra::vector![
166+
0.005, 0.005, 0.000_001, 0.000_001
167+
]),
168+
}),
169+
last_seen: Time::zero(),
170+
validity: 1.0,
171+
};
172+
173+
hypothesis.predict(
174+
Duration::ZERO,
175+
Isometry2::identity(),
176+
1.0,
177+
Matrix4::zeros(),
178+
Matrix2::zeros(),
179+
0.5,
180+
);
181+
182+
assert!(matches!(hypothesis.mode, BallMode::Moving(_)));
183+
}
184+
}

crates/nodes/ball_filter/src/lib.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ fn mahalanobis_matrix_of_hypotheses_and_percepts(
398398
let ball = hypothesis.position();
399399

400400
let residual = percept.percept_in_ground.mean - ball.position.inner.coords;
401-
let covariance = hypothesis.position_covariance();
401+
let covariance = hypothesis.position_covariance() + percept.percept_in_ground.covariance;
402402

403403
let mahalanobis_distance = residual.dot(
404404
&covariance
@@ -577,4 +577,31 @@ mod tests {
577577
assert_eq!(assignment.len(), 2);
578578
assert_eq!(assignment.into_iter().flatten().count(), 2);
579579
}
580+
581+
#[test]
582+
fn matching_cost_accounts_for_percept_covariance() {
583+
let hypothesis = BallHypothesis {
584+
mode: BallMode::Moving(MultivariateNormalDistribution {
585+
mean: nalgebra::vector![0.0, 0.0, 0.0, 0.0],
586+
covariance: Matrix4::from_diagonal(&nalgebra::vector![0.01, 0.01, 1.0, 1.0]),
587+
}),
588+
last_seen: Time::zero(),
589+
validity: 1.0,
590+
};
591+
let percept = BallPercept {
592+
percept_in_ground: MultivariateNormalDistribution {
593+
mean: vector![1.0, 0.0],
594+
covariance: Matrix2::identity() * 100.0,
595+
},
596+
image_location: Circle::new(point![0.0, 0.0], 1.0),
597+
};
598+
599+
let costs = mahalanobis_matrix_of_hypotheses_and_percepts(&[hypothesis], &[percept]);
600+
let cost = costs[(0, 0)].into_inner();
601+
602+
assert!(
603+
cost > -1.0,
604+
"uncertain percept should not be treated as a precise outlier, got cost {cost}"
605+
);
606+
}
580607
}

crates/world_state/src/ball_filter.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use coordinate_systems::{Ground, Pixel};
1616
use framework::{AdditionalOutput, HistoricInput, MainOutput, PerceptionInput};
1717
use geometry::circle::Circle;
1818
use linear_algebra::{IntoFramed, Isometry2};
19-
use projection::{Projection, camera_matrix::CameraMatrix};
19+
use projection::{camera_matrix::CameraMatrix, Projection};
2020
use types::{
2121
ball_detection::BallPercept,
2222
ball_position::{BallPosition, HypotheticalBallPosition},
@@ -319,7 +319,7 @@ fn mahalanobis_matrix_of_hypotheses_and_percepts(
319319
let ball = hypothesis.position();
320320

321321
let residual = percept.percept_in_ground.mean - ball.position.inner.coords;
322-
let covariance = hypothesis.position_covariance();
322+
let covariance = hypothesis.position_covariance() + percept.percept_in_ground.covariance;
323323

324324
let mahalanobis_distance = residual.dot(
325325
&covariance
@@ -502,4 +502,31 @@ mod tests {
502502
assert_eq!(assignment.len(), 2);
503503
assert_eq!(assignment.into_iter().flatten().count(), 2);
504504
}
505+
506+
#[test]
507+
fn matching_cost_accounts_for_percept_covariance() {
508+
let hypothesis = BallHypothesis {
509+
mode: BallMode::Moving(MultivariateNormalDistribution {
510+
mean: nalgebra::vector![0.0, 0.0, 0.0, 0.0],
511+
covariance: Matrix4::from_diagonal(&nalgebra::vector![0.01, 0.01, 1.0, 1.0]),
512+
}),
513+
last_seen: Time::zero(),
514+
validity: 1.0,
515+
};
516+
let percept = BallPercept {
517+
percept_in_ground: MultivariateNormalDistribution {
518+
mean: vector![1.0, 0.0],
519+
covariance: Matrix2::identity() * 100.0,
520+
},
521+
image_location: Circle::new(point![0.0, 0.0], 1.0),
522+
};
523+
524+
let costs = mahalanobis_matrix_of_hypotheses_and_percepts(&[hypothesis], &[percept]);
525+
let cost = costs[(0, 0)].into_inner();
526+
527+
assert!(
528+
cost > -1.0,
529+
"uncertain percept should not be treated as a precise outlier, got cost {cost}"
530+
);
531+
}
505532
}

etc/parameters/default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@
628628
"secs": 20
629629
},
630630
"log_likelihood_of_zero_velocity_threshold": 0.5,
631-
"maximum_matching_cost": 0.25,
631+
"maximum_matching_cost": 5.9914646,
632632
"maximum_matching_cost_validity_penalty_factor": 0.14,
633633
"maximum_number_of_hypotheses": 15,
634634
"noise": {

0 commit comments

Comments
 (0)