Skip to content

Commit abe8e3c

Browse files
feat(ekf_localizer): add covariance ellipse diagnostics (#7708)
* Added ellipse diagnostics to ekf Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Removed an unnecessary parenthesis Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Fixed to ellipse_scale Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Fixed to ellipse_scale Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Updated ekf_diagnostics.png Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Added condition Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> * Fixed "and" to "or" Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> --------- Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp>
1 parent 250562d commit abe8e3c

10 files changed

+101
-4
lines changed

localization/ekf_localizer/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,12 @@ Note that, although the dimension gets larger since the analytical expansion can
186186
- The number of consecutive no measurement update via the Pose/Twist topic exceeds the `pose_no_update_count_threshold_warn`/`twist_no_update_count_threshold_warn`.
187187
- The timestamp of the Pose/Twist topic is beyond the delay compensation range.
188188
- The Pose/Twist topic is beyond the range of Mahalanobis distance for covariance estimation.
189+
- The covariance ellipse is bigger than threshold `warn_ellipse_size` for long axis or `warn_ellipse_size_lateral_direction` for lateral_direction.
189190

190191
### The conditions that result in an ERROR state
191192

192193
- The number of consecutive no measurement update via the Pose/Twist topic exceeds the `pose_no_update_count_threshold_error`/`twist_no_update_count_threshold_error`.
194+
- The covariance ellipse is bigger than threshold `error_ellipse_size` for long axis or `error_ellipse_size_lateral_direction` for lateral_direction.
193195

194196
## Known issues
195197

localization/ekf_localizer/config/ekf_localizer.param.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@
3939
pose_no_update_count_threshold_error: 100
4040
twist_no_update_count_threshold_warn: 50
4141
twist_no_update_count_threshold_error: 100
42+
ellipse_scale: 3.0
43+
error_ellipse_size: 1.5
44+
warn_ellipse_size: 1.2
45+
error_ellipse_size_lateral_direction: 0.3
46+
warn_ellipse_size_lateral_direction: 0.25
4247

4348
misc:
4449
# for velocity measurement limitation (Set 0.0 if you want to ignore)

localization/ekf_localizer/include/ekf_localizer/diagnostics.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ diagnostic_msgs::msg::DiagnosticStatus check_measurement_delay_gate(
3333
diagnostic_msgs::msg::DiagnosticStatus check_measurement_mahalanobis_gate(
3434
const std::string & measurement_type, const bool is_passed_mahalanobis_gate,
3535
const double mahalanobis_distance, const double mahalanobis_distance_threshold);
36+
diagnostic_msgs::msg::DiagnosticStatus check_covariance_ellipse(
37+
const std::string & name, const double curr_size, const double warn_threshold,
38+
const double error_threshold);
3639

3740
diagnostic_msgs::msg::DiagnosticStatus merge_diagnostic_status(
3841
const std::vector<diagnostic_msgs::msg::DiagnosticStatus> & stat_array);

localization/ekf_localizer/include/ekf_localizer/ekf_localizer.hpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,8 @@ class EKFLocalizer : public rclcpp::Node
216216
/**
217217
* @brief publish diagnostics message
218218
*/
219-
void publish_diagnostics(const rclcpp::Time & current_time);
219+
void publish_diagnostics(
220+
const geometry_msgs::msg::PoseStamped & current_ekf_pose, const rclcpp::Time & current_time);
220221

221222
/**
222223
* @brief update simple 1d filter

localization/ekf_localizer/include/ekf_localizer/hyper_parameters.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ class HyperParameters
5757
node->declare_parameter<int>("diagnostics.twist_no_update_count_threshold_warn")),
5858
twist_no_update_count_threshold_error(
5959
node->declare_parameter<int>("diagnostics.twist_no_update_count_threshold_error")),
60+
ellipse_scale(node->declare_parameter<double>("diagnostics.ellipse_scale")),
61+
error_ellipse_size(node->declare_parameter<double>("diagnostics.error_ellipse_size")),
62+
warn_ellipse_size(node->declare_parameter<double>("diagnostics.warn_ellipse_size")),
63+
error_ellipse_size_lateral_direction(
64+
node->declare_parameter<double>("diagnostics.error_ellipse_size_lateral_direction")),
65+
warn_ellipse_size_lateral_direction(
66+
node->declare_parameter<double>("diagnostics.warn_ellipse_size_lateral_direction")),
6067
threshold_observable_velocity_mps(
6168
node->declare_parameter<double>("misc.threshold_observable_velocity_mps"))
6269
{
@@ -86,6 +93,12 @@ class HyperParameters
8693
const size_t pose_no_update_count_threshold_error;
8794
const size_t twist_no_update_count_threshold_warn;
8895
const size_t twist_no_update_count_threshold_error;
96+
double ellipse_scale;
97+
double error_ellipse_size;
98+
double warn_ellipse_size;
99+
double error_ellipse_size_lateral_direction;
100+
double warn_ellipse_size_lateral_direction;
101+
89102
const double threshold_observable_velocity_mps;
90103
};
91104

Loading

localization/ekf_localizer/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
<depend>fmt</depend>
2929
<depend>geometry_msgs</depend>
3030
<depend>kalman_filter</depend>
31+
<depend>localization_util</depend>
3132
<depend>nav_msgs</depend>
3233
<depend>rclcpp</depend>
3334
<depend>rclcpp_components</depend>

localization/ekf_localizer/schema/sub/diagnostics.sub_schema.json

+25
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,31 @@
2424
"type": "integer",
2525
"description": "The threshold at which an ERROR state is triggered due to the Twist Topic update not happening continuously for a certain number of times",
2626
"default": 100
27+
},
28+
"ellipse_scale": {
29+
"type": "number",
30+
"description": "The scale factor to apply the error ellipse size",
31+
"default": 3.0
32+
},
33+
"error_ellipse_size": {
34+
"type": "number",
35+
"description": "The long axis size of the error ellipse to trigger a ERROR state",
36+
"default": 1.5
37+
},
38+
"warn_ellipse_size": {
39+
"type": "number",
40+
"description": "The long axis size of the error ellipse to trigger a WARN state",
41+
"default": 1.2
42+
},
43+
"error_ellipse_size_lateral_direction": {
44+
"type": "number",
45+
"description": "The lateral direction size of the error ellipse to trigger a ERROR state",
46+
"default": 0.3
47+
},
48+
"warn_ellipse_size_lateral_direction": {
49+
"type": "number",
50+
"description": "The lateral direction size of the error ellipse to trigger a WARN state",
51+
"default": 0.25
2752
}
2853
},
2954
"required": [

localization/ekf_localizer/src/diagnostics.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,39 @@ diagnostic_msgs::msg::DiagnosticStatus check_measurement_mahalanobis_gate(
139139
return stat;
140140
}
141141

142+
diagnostic_msgs::msg::DiagnosticStatus check_covariance_ellipse(
143+
const std::string & name, const double curr_size, const double warn_threshold,
144+
const double error_threshold)
145+
{
146+
diagnostic_msgs::msg::DiagnosticStatus stat;
147+
148+
diagnostic_msgs::msg::KeyValue key_value;
149+
key_value.key = name + "_size";
150+
key_value.value = std::to_string(curr_size);
151+
stat.values.push_back(key_value);
152+
153+
key_value.key = name + "_warn_threshold";
154+
key_value.value = std::to_string(warn_threshold);
155+
stat.values.push_back(key_value);
156+
157+
key_value.key = name + "_error_threshold";
158+
key_value.value = std::to_string(error_threshold);
159+
stat.values.push_back(key_value);
160+
161+
stat.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
162+
stat.message = "OK";
163+
if (curr_size >= warn_threshold) {
164+
stat.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
165+
stat.message = "[WARN]" + name + " is large";
166+
}
167+
if (curr_size >= error_threshold) {
168+
stat.level = diagnostic_msgs::msg::DiagnosticStatus::ERROR;
169+
stat.message = "[ERROR]" + name + " is large";
170+
}
171+
172+
return stat;
173+
}
174+
142175
// The highest level within the stat_array will be reflected in the merged_stat.
143176
// When all stat_array entries are 'OK,' the message of merged_stat will be "OK"
144177
diagnostic_msgs::msg::DiagnosticStatus merge_diagnostic_status(

localization/ekf_localizer/src/ekf_localizer.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "ekf_localizer/diagnostics.hpp"
1818
#include "ekf_localizer/string.hpp"
1919
#include "ekf_localizer/warning_message.hpp"
20+
#include "localization_util/covariance_ellipse.hpp"
2021

2122
#include <autoware/universe_utils/geometry/geometry.hpp>
2223
#include <autoware/universe_utils/math/unit_conversion.hpp>
@@ -148,7 +149,7 @@ void EKFLocalizer::timer_callback()
148149
if (!is_activated_) {
149150
warning_->warn_throttle(
150151
"The node is not activated. Provide initial pose to pose_initializer", 2000);
151-
publish_diagnostics(current_time);
152+
publish_diagnostics(geometry_msgs::msg::PoseStamped{}, current_time);
152153
return;
153154
}
154155

@@ -241,7 +242,7 @@ void EKFLocalizer::timer_callback()
241242

242243
/* publish ekf result */
243244
publish_estimate_result(current_ekf_pose, current_biased_ekf_pose, current_ekf_twist);
244-
publish_diagnostics(current_time);
245+
publish_diagnostics(current_ekf_pose, current_time);
245246
}
246247

247248
/*
@@ -390,7 +391,8 @@ void EKFLocalizer::publish_estimate_result(
390391
pub_odom_->publish(odometry);
391392
}
392393

393-
void EKFLocalizer::publish_diagnostics(const rclcpp::Time & current_time)
394+
void EKFLocalizer::publish_diagnostics(
395+
const geometry_msgs::msg::PoseStamped & current_ekf_pose, const rclcpp::Time & current_time)
394396
{
395397
std::vector<diagnostic_msgs::msg::DiagnosticStatus> diag_status_array;
396398

@@ -418,6 +420,18 @@ void EKFLocalizer::publish_diagnostics(const rclcpp::Time & current_time)
418420
diag_status_array.push_back(check_measurement_mahalanobis_gate(
419421
"twist", twist_diag_info_.is_passed_mahalanobis_gate, twist_diag_info_.mahalanobis_distance,
420422
params_.twist_gate_dist));
423+
424+
geometry_msgs::msg::PoseWithCovariance pose_cov;
425+
pose_cov.pose = current_ekf_pose.pose;
426+
pose_cov.covariance = ekf_module_->get_current_pose_covariance();
427+
const autoware::localization_util::Ellipse ellipse =
428+
autoware::localization_util::calculate_xy_ellipse(pose_cov, params_.ellipse_scale);
429+
diag_status_array.push_back(check_covariance_ellipse(
430+
"cov_ellipse_long_axis", ellipse.long_radius, params_.warn_ellipse_size,
431+
params_.error_ellipse_size));
432+
diag_status_array.push_back(check_covariance_ellipse(
433+
"cov_ellipse_lateral_direction", ellipse.size_lateral_direction,
434+
params_.warn_ellipse_size_lateral_direction, params_.error_ellipse_size_lateral_direction));
421435
}
422436

423437
diagnostic_msgs::msg::DiagnosticStatus diag_merged_status;

0 commit comments

Comments
 (0)