Skip to content

Commit 6e55974

Browse files
refactor(localization_util): add covariance_ellipse to localization_util (#7706)
Added covariance_ellipse to localization_util Signed-off-by: Shintaro Sakoda <shintaro.sakoda@tier4.jp> Signed-off-by: Simon Eisenmann <simon.eisenmann@driveblocks.ai>
1 parent 27b98c0 commit 6e55974

File tree

6 files changed

+143
-77
lines changed

6 files changed

+143
-77
lines changed

localization/localization_error_monitor/include/localization_error_monitor/localization_error_monitor.hpp

+3-13
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
#ifndef LOCALIZATION_ERROR_MONITOR__LOCALIZATION_ERROR_MONITOR_HPP_
1616
#define LOCALIZATION_ERROR_MONITOR__LOCALIZATION_ERROR_MONITOR_HPP_
1717

18+
#include "localization_util/covariance_ellipse.hpp"
19+
1820
#include <Eigen/Dense>
1921
#include <autoware/universe_utils/ros/logger_level_configure.hpp>
2022
#include <rclcpp/rclcpp.hpp>
@@ -25,15 +27,6 @@
2527

2628
#include <memory>
2729

28-
struct Ellipse
29-
{
30-
double long_radius;
31-
double short_radius;
32-
double yaw;
33-
Eigen::Matrix2d P;
34-
double size_lateral_direction;
35-
};
36-
3730
class LocalizationErrorMonitor : public rclcpp::Node
3831
{
3932
private:
@@ -50,12 +43,9 @@ class LocalizationErrorMonitor : public rclcpp::Node
5043
double warn_ellipse_size_;
5144
double error_ellipse_size_lateral_direction_;
5245
double warn_ellipse_size_lateral_direction_;
53-
Ellipse ellipse_;
46+
autoware::localization_util::Ellipse ellipse_;
5447

5548
void on_odom(nav_msgs::msg::Odometry::ConstSharedPtr input_msg);
56-
visualization_msgs::msg::Marker create_ellipse_marker(
57-
const Ellipse & ellipse, nav_msgs::msg::Odometry::ConstSharedPtr odom);
58-
static double measure_size_ellipse_along_body_frame(const Eigen::Matrix2d & Pinv, double theta);
5949

6050
public:
6151
explicit LocalizationErrorMonitor(const rclcpp::NodeOptions & options);

localization/localization_error_monitor/package.xml

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
<depend>autoware_universe_utils</depend>
2424
<depend>diagnostic_msgs</depend>
2525
<depend>diagnostic_updater</depend>
26+
<depend>localization_util</depend>
2627
<depend>nav_msgs</depend>
2728
<depend>rclcpp_components</depend>
2829
<depend>tf2</depend>

localization/localization_error_monitor/src/localization_error_monitor.cpp

+4-64
Original file line numberDiff line numberDiff line change
@@ -58,61 +58,12 @@ LocalizationErrorMonitor::LocalizationErrorMonitor(const rclcpp::NodeOptions & o
5858
logger_configure_ = std::make_unique<autoware::universe_utils::LoggerLevelConfigure>(this);
5959
}
6060

61-
visualization_msgs::msg::Marker LocalizationErrorMonitor::create_ellipse_marker(
62-
const Ellipse & ellipse, nav_msgs::msg::Odometry::ConstSharedPtr odom)
63-
{
64-
tf2::Quaternion quat;
65-
quat.setEuler(0, 0, ellipse.yaw);
66-
67-
const double ellipse_long_radius = std::min(ellipse.long_radius, 30.0);
68-
const double ellipse_short_radius = std::min(ellipse.short_radius, 30.0);
69-
visualization_msgs::msg::Marker marker;
70-
marker.header = odom->header;
71-
marker.header.stamp = this->now();
72-
marker.ns = "error_ellipse";
73-
marker.id = 0;
74-
marker.type = visualization_msgs::msg::Marker::SPHERE;
75-
marker.action = visualization_msgs::msg::Marker::ADD;
76-
marker.pose = odom->pose.pose;
77-
marker.pose.orientation = tf2::toMsg(quat);
78-
marker.scale.x = ellipse_long_radius * 2;
79-
marker.scale.y = ellipse_short_radius * 2;
80-
marker.scale.z = 0.01;
81-
marker.color.a = 0.1;
82-
marker.color.r = 0.0;
83-
marker.color.g = 0.0;
84-
marker.color.b = 1.0;
85-
return marker;
86-
}
87-
8861
void LocalizationErrorMonitor::on_odom(nav_msgs::msg::Odometry::ConstSharedPtr input_msg)
8962
{
90-
// create xy covariance (2x2 matrix)
91-
// input geometry_msgs::PoseWithCovariance contain 6x6 matrix
92-
Eigen::Matrix2d xy_covariance;
93-
const auto cov = input_msg->pose.covariance;
94-
xy_covariance(0, 0) = cov[0 * 6 + 0];
95-
xy_covariance(0, 1) = cov[0 * 6 + 1];
96-
xy_covariance(1, 0) = cov[1 * 6 + 0];
97-
xy_covariance(1, 1) = cov[1 * 6 + 1];
98-
99-
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver(xy_covariance);
100-
101-
// eigen values and vectors are sorted in ascending order
102-
ellipse_.long_radius = scale_ * std::sqrt(eigensolver.eigenvalues()(1));
103-
ellipse_.short_radius = scale_ * std::sqrt(eigensolver.eigenvalues()(0));
104-
105-
// principal component vector
106-
const Eigen::Vector2d pc_vector = eigensolver.eigenvectors().col(1);
107-
ellipse_.yaw = std::atan2(pc_vector.y(), pc_vector.x());
108-
109-
// ellipse size along lateral direction (body-frame)
110-
ellipse_.P = xy_covariance;
111-
const double yaw_vehicle = tf2::getYaw(input_msg->pose.pose.orientation);
112-
ellipse_.size_lateral_direction =
113-
scale_ * measure_size_ellipse_along_body_frame(ellipse_.P.inverse(), yaw_vehicle);
114-
115-
const auto ellipse_marker = create_ellipse_marker(ellipse_, input_msg);
63+
ellipse_ = autoware::localization_util::calculate_xy_ellipse(input_msg->pose, scale_);
64+
65+
const auto ellipse_marker = autoware::localization_util::create_ellipse_marker(
66+
ellipse_, input_msg->header, input_msg->pose);
11667
ellipse_marker_pub_->publish(ellipse_marker);
11768

11869
// diagnostics
@@ -134,16 +85,5 @@ void LocalizationErrorMonitor::on_odom(nav_msgs::msg::Odometry::ConstSharedPtr i
13485
diag_pub_->publish(diag_msg);
13586
}
13687

137-
double LocalizationErrorMonitor::measure_size_ellipse_along_body_frame(
138-
const Eigen::Matrix2d & Pinv, const double theta)
139-
{
140-
Eigen::MatrixXd e(2, 1);
141-
e(0, 0) = std::cos(theta);
142-
e(1, 0) = std::sin(theta);
143-
144-
double d = std::sqrt((e.transpose() * Pinv * e)(0, 0) / Pinv.determinant());
145-
return d;
146-
}
147-
14888
#include <rclcpp_components/register_node_macro.hpp>
14989
RCLCPP_COMPONENTS_REGISTER_NODE(LocalizationErrorMonitor)

localization/localization_util/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ ament_auto_add_library(localization_util SHARED
88
src/util_func.cpp
99
src/smart_pose_buffer.cpp
1010
src/tree_structured_parzen_estimator.cpp
11+
src/covariance_ellipse.cpp
1112
)
1213

1314
if(BUILD_TESTING)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2024 Autoware Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef LOCALIZATION_UTIL__COVARIANCE_ELLIPSE_HPP_
16+
#define LOCALIZATION_UTIL__COVARIANCE_ELLIPSE_HPP_
17+
18+
#include <Eigen/Dense>
19+
20+
#include <geometry_msgs/msg/pose_with_covariance.hpp>
21+
#include <visualization_msgs/msg/marker_array.hpp>
22+
23+
namespace autoware::localization_util
24+
{
25+
26+
struct Ellipse
27+
{
28+
double long_radius;
29+
double short_radius;
30+
double yaw;
31+
Eigen::Matrix2d P;
32+
double size_lateral_direction;
33+
};
34+
35+
Ellipse calculate_xy_ellipse(
36+
const geometry_msgs::msg::PoseWithCovariance & pose_with_covariance, const double scale);
37+
38+
visualization_msgs::msg::Marker create_ellipse_marker(
39+
const Ellipse & ellipse, const std_msgs::msg::Header & header,
40+
const geometry_msgs::msg::PoseWithCovariance & pose_with_covariance);
41+
42+
} // namespace autoware::localization_util
43+
44+
#endif // LOCALIZATION_UTIL__COVARIANCE_ELLIPSE_HPP_
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright 2024 Autoware Foundation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "localization_util/covariance_ellipse.hpp"
16+
17+
#include <tf2/utils.h>
18+
#ifdef ROS_DISTRO_GALACTIC
19+
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
20+
#else
21+
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
22+
#endif
23+
24+
namespace autoware::localization_util
25+
{
26+
27+
Ellipse calculate_xy_ellipse(
28+
const geometry_msgs::msg::PoseWithCovariance & pose_with_covariance, const double scale)
29+
{
30+
// input geometry_msgs::PoseWithCovariance contain 6x6 matrix
31+
Eigen::Matrix2d xy_covariance;
32+
const auto cov = pose_with_covariance.covariance;
33+
xy_covariance(0, 0) = cov[0 * 6 + 0];
34+
xy_covariance(0, 1) = cov[0 * 6 + 1];
35+
xy_covariance(1, 0) = cov[1 * 6 + 0];
36+
xy_covariance(1, 1) = cov[1 * 6 + 1];
37+
38+
Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver(xy_covariance);
39+
40+
Ellipse ellipse;
41+
42+
// eigen values and vectors are sorted in ascending order
43+
ellipse.long_radius = scale * std::sqrt(eigensolver.eigenvalues()(1));
44+
ellipse.short_radius = scale * std::sqrt(eigensolver.eigenvalues()(0));
45+
46+
// principal component vector
47+
const Eigen::Vector2d pc_vector = eigensolver.eigenvectors().col(1);
48+
ellipse.yaw = std::atan2(pc_vector.y(), pc_vector.x());
49+
50+
// ellipse size along lateral direction (body-frame)
51+
ellipse.P = xy_covariance;
52+
const double yaw_vehicle = tf2::getYaw(pose_with_covariance.pose.orientation);
53+
const Eigen::Matrix2d & p_inv = ellipse.P.inverse();
54+
Eigen::MatrixXd e(2, 1);
55+
e(0, 0) = std::cos(yaw_vehicle);
56+
e(1, 0) = std::sin(yaw_vehicle);
57+
const double d = std::sqrt((e.transpose() * p_inv * e)(0, 0) / p_inv.determinant());
58+
ellipse.size_lateral_direction = scale * d;
59+
60+
return ellipse;
61+
}
62+
63+
visualization_msgs::msg::Marker create_ellipse_marker(
64+
const Ellipse & ellipse, const std_msgs::msg::Header & header,
65+
const geometry_msgs::msg::PoseWithCovariance & pose_with_covariance)
66+
{
67+
tf2::Quaternion quat;
68+
quat.setEuler(0, 0, ellipse.yaw);
69+
70+
const double ellipse_long_radius = std::min(ellipse.long_radius, 30.0);
71+
const double ellipse_short_radius = std::min(ellipse.short_radius, 30.0);
72+
visualization_msgs::msg::Marker marker;
73+
marker.header = header;
74+
marker.ns = "error_ellipse";
75+
marker.id = 0;
76+
marker.type = visualization_msgs::msg::Marker::SPHERE;
77+
marker.action = visualization_msgs::msg::Marker::ADD;
78+
marker.pose = pose_with_covariance.pose;
79+
marker.pose.orientation = tf2::toMsg(quat);
80+
marker.scale.x = ellipse_long_radius * 2;
81+
marker.scale.y = ellipse_short_radius * 2;
82+
marker.scale.z = 0.01;
83+
marker.color.a = 0.1;
84+
marker.color.r = 0.0;
85+
marker.color.g = 0.0;
86+
marker.color.b = 1.0;
87+
return marker;
88+
}
89+
90+
} // namespace autoware::localization_util

0 commit comments

Comments
 (0)