|
23 | 23 | #include "nav2_core/controller_exceptions.hpp"
|
24 | 24 | #include "nav2_ros_common/node_utils.hpp"
|
25 | 25 | #include "nav2_util/geometry_utils.hpp"
|
| 26 | +#include "nav2_util/path_utils.hpp" |
26 | 27 | #include "nav2_controller/controller_server.hpp"
|
27 | 28 |
|
28 | 29 | using namespace std::chrono_literals;
|
@@ -228,6 +229,7 @@ ControllerServer::on_configure(const rclcpp_lifecycle::State & state)
|
228 | 229 |
|
229 | 230 | double costmap_update_timeout_dbl;
|
230 | 231 | get_parameter("costmap_update_timeout", costmap_update_timeout_dbl);
|
| 232 | + tracking_error_pub_ = create_publisher<nav2_msgs::msg::TrackingError>("tracking_error", 10); |
231 | 233 | costmap_update_timeout_ = rclcpp::Duration::from_seconds(costmap_update_timeout_dbl);
|
232 | 234 |
|
233 | 235 | // Create the action server that we implement with our followPath method
|
@@ -500,6 +502,8 @@ void ControllerServer::computeControl()
|
500 | 502 |
|
501 | 503 | computeAndPublishVelocity();
|
502 | 504 |
|
| 505 | + publishTrackingState(); |
| 506 | + |
503 | 507 | if (isGoalReached()) {
|
504 | 508 | RCLCPP_INFO(get_logger(), "Reached the goal!");
|
505 | 509 | break;
|
@@ -750,6 +754,66 @@ void ControllerServer::updateGlobalPath()
|
750 | 754 | }
|
751 | 755 | }
|
752 | 756 |
|
| 757 | +void ControllerServer::publishTrackingState() |
| 758 | +{ |
| 759 | + if (current_path_.poses.size() < 2) { |
| 760 | + RCLCPP_DEBUG(get_logger(), "Path has fewer than 2 points, cannot compute tracking error."); |
| 761 | + return; |
| 762 | + } |
| 763 | + |
| 764 | + geometry_msgs::msg::PoseStamped robot_pose; |
| 765 | + if (!getRobotPose(robot_pose)) { |
| 766 | + RCLCPP_WARN(get_logger(), "Failed to obtain robot pose, skipping tracking error publication."); |
| 767 | + return; |
| 768 | + } |
| 769 | + |
| 770 | +// Frame checks |
| 771 | + geometry_msgs::msg::PoseStamped robot_pose_in_path_frame; |
| 772 | + if (!nav2_util::transformPoseInTargetFrame( |
| 773 | + robot_pose, robot_pose_in_path_frame, *costmap_ros_->getTfBuffer(), |
| 774 | + current_path_.header.frame_id, costmap_ros_->getTransformTolerance())) |
| 775 | + { |
| 776 | + RCLCPP_WARN(get_logger(), "Failed to transform robot pose to path frame."); |
| 777 | + return; |
| 778 | + } |
| 779 | + |
| 780 | + geometry_msgs::msg::PoseStamped end_pose_in_robot_frame; |
| 781 | + if (!nav2_util::transformPoseInTargetFrame( |
| 782 | + end_pose_, end_pose_in_robot_frame, *costmap_ros_->getTfBuffer(), |
| 783 | + robot_pose.header.frame_id, costmap_ros_->getTransformTolerance())) |
| 784 | + { |
| 785 | + RCLCPP_WARN(get_logger(), "Failed to transform end pose to robot frame."); |
| 786 | + return; |
| 787 | + } |
| 788 | + |
| 789 | + const double distance_to_goal = nav2_util::geometry_utils::euclidean_distance( |
| 790 | + robot_pose, end_pose_in_robot_frame); |
| 791 | + |
| 792 | + const auto path_search_result = nav2_util::distance_from_path( |
| 793 | + current_path_, robot_pose_in_path_frame.pose, start_index_, search_window_); |
| 794 | + |
| 795 | + const size_t closest_idx = path_search_result.closest_segment_index; |
| 796 | + start_index_ = closest_idx; |
| 797 | + |
| 798 | + const auto & segment_start = current_path_.poses[closest_idx]; |
| 799 | + const auto & segment_end = current_path_.poses[closest_idx + 1]; |
| 800 | + |
| 801 | + // Cross product is for getting which side of the track |
| 802 | + double cross_product = nav2_util::geometry_utils::cross_product_2d( |
| 803 | + robot_pose_in_path_frame.pose.position, segment_start.pose, segment_end.pose); |
| 804 | + |
| 805 | + nav2_msgs::msg::TrackingError tracking_error_msg; |
| 806 | + tracking_error_msg.header.stamp = now(); |
| 807 | + tracking_error_msg.header.frame_id = robot_pose.header.frame_id; |
| 808 | + tracking_error_msg.tracking_error = path_search_result.distance; |
| 809 | + tracking_error_msg.last_index = closest_idx; |
| 810 | + tracking_error_msg.cross_product = cross_product; |
| 811 | + tracking_error_msg.distance_to_goal = distance_to_goal; |
| 812 | + tracking_error_msg.robot_pose = robot_pose; |
| 813 | + |
| 814 | + tracking_error_pub_->publish(tracking_error_msg); |
| 815 | +} |
| 816 | + |
753 | 817 | void ControllerServer::publishVelocity(const geometry_msgs::msg::TwistStamped & velocity)
|
754 | 818 | {
|
755 | 819 | auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
|
|
0 commit comments