-
Notifications
You must be signed in to change notification settings - Fork 34
Add localization quality estimation metric #563
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
base: main
Are you sure you want to change the base?
Changes from 4 commits
d72f1ac
6c839dc
f731fc2
ea0db5c
62117bc
9c8d158
dc1d4d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
|
|
||
| #include <beluga_ros/amcl.hpp> | ||
|
|
||
| #include <algorithm> | ||
| #include <beluga/actions/assign.hpp> | ||
| #include <beluga/actions/normalize.hpp> | ||
| #include <beluga/actions/propagate.hpp> | ||
|
|
@@ -22,6 +23,9 @@ | |
| #include <beluga/views/random_intersperse.hpp> | ||
| #include <beluga/views/take_while_kld.hpp> | ||
| #include <cmath> | ||
| #include <limits> | ||
| #include <random> | ||
| #include <vector> | ||
|
|
||
| namespace beluga_ros { | ||
|
|
||
|
|
@@ -122,7 +126,46 @@ auto Amcl::update( | |
| } | ||
|
|
||
| force_update_ = false; | ||
| return beluga::cluster_based_estimate(beluga::views::states(particles_), beluga::views::weights(particles_)); | ||
| auto estimate = beluga::cluster_based_estimate(beluga::views::states(particles_), beluga::views::weights(particles_)); | ||
| last_quality_ = compute_quality(estimate.second); | ||
| return estimate; | ||
| } | ||
|
|
||
| double Amcl::compute_quality(const Sophus::Matrix3d& actual_covariance) { | ||
| const std::size_t n = params_.min_particles; | ||
|
|
||
| // a known seed is required to provide the exact same reference each time quality is computed. | ||
| std::mt19937 gen{42}; | ||
| std::normal_distribution<double> dx{0.0, params_.expected_pose_x_stddev}; | ||
| std::normal_distribution<double> dy{0.0, params_.expected_pose_y_stddev}; | ||
| std::normal_distribution<double> dyaw{0.0, params_.expected_pose_yaw_stddev}; | ||
|
|
||
| std::vector<Sophus::SE2d> ref_states; | ||
|
papalmac marked this conversation as resolved.
Outdated
|
||
| ref_states.reserve(n); | ||
| for (std::size_t i = 0; i < n; ++i) { | ||
| ref_states.emplace_back(Sophus::SO2d{dyaw(gen)}, Sophus::Vector2d{dx(gen), dy(gen)}); | ||
| } | ||
|
|
||
| std::visit( | ||
| [&](const auto& motion_model) { | ||
| auto sampling_fn = motion_model(control_action_window_); | ||
| for (auto& state : ref_states) { | ||
| state = sampling_fn(state, gen); | ||
| } | ||
| }, | ||
| motion_model_); | ||
|
|
||
| const std::vector<double> uniform_weights(n, 1.0); | ||
| const auto [ref_mean, ref_covariance] = beluga::estimate(ref_states, uniform_weights); | ||
|
|
||
| double quality = 1.0; | ||
| for (int i = 0; i < 3; ++i) { | ||
| const double actual = actual_covariance.coeff(i, i); | ||
| if (actual > std::numeric_limits<double>::epsilon()) { | ||
| quality = std::min(quality, ref_covariance.coeff(i, i) / actual); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a bit distorsive than the quotient is made in terms of the squared values, since that will amplify any difference in the standard deviations.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. having a single index for all three dimensions clouds poor choices for a particular dimension. I think all three should be outputs.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, calculating the min over the three with no averaging is very biasing, since you only need one of the values to take a tail end value of the distribution to make a huge difference in the results.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment addressed in 9c8d158 |
||
| } | ||
| } | ||
| return std::clamp(quality, 0.0, 1.0); | ||
| } | ||
|
|
||
| } // namespace beluga_ros | ||
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.
@papalmac meta, maybe followup: I think it may be worth to move this into the core, taking the nominal distribution, the motion model, and the last available estimate.
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 will also help unit testing this. That's step 1. Then we'll need to do some benchmarking and/or testing in the field. @agalbachicar would you be open to collaborate on that?