@@ -55,6 +55,7 @@ ControllerServer::ControllerServer(const rclcpp::NodeOptions & options)
55
55
declare_parameter (" min_x_velocity_threshold" , rclcpp::ParameterValue (0.0001 ));
56
56
declare_parameter (" min_y_velocity_threshold" , rclcpp::ParameterValue (0.0001 ));
57
57
declare_parameter (" min_theta_velocity_threshold" , rclcpp::ParameterValue (0.0001 ));
58
+ declare_parameter (" search_window" , rclcpp::ParameterValue (5.0 ));
58
59
59
60
declare_parameter (" speed_limit_topic" , rclcpp::ParameterValue (" speed_limit" ));
60
61
@@ -134,6 +135,7 @@ ControllerServer::on_configure(const rclcpp_lifecycle::State & state)
134
135
get_parameter (" failure_tolerance" , failure_tolerance_);
135
136
get_parameter (" use_realtime_priority" , use_realtime_priority_);
136
137
get_parameter (" publish_zero_velocity" , publish_zero_velocity_);
138
+ get_parameter (" search_window" , search_window_);
137
139
138
140
costmap_ros_->configure ();
139
141
// Launch a thread to run the costmap node
@@ -225,6 +227,7 @@ ControllerServer::on_configure(const rclcpp_lifecycle::State & state)
225
227
226
228
odom_sub_ = std::make_unique<nav2_util::OdomSmoother>(node, odom_duration, odom_topic);
227
229
vel_publisher_ = std::make_unique<nav2_util::TwistPublisher>(node, " cmd_vel" );
230
+ tracking_error_pub_ = create_publisher<nav2_msgs::msg::TrackingError>(" tracking_error" , 10 );
228
231
229
232
double costmap_update_timeout_dbl;
230
233
get_parameter (" costmap_update_timeout" , costmap_update_timeout_dbl);
@@ -500,6 +503,8 @@ void ControllerServer::computeControl()
500
503
501
504
computeAndPublishVelocity ();
502
505
506
+ publishTrackingState ();
507
+
503
508
if (isGoalReached ()) {
504
509
RCLCPP_INFO (get_logger (), " Reached the goal!" );
505
510
break ;
@@ -604,16 +609,18 @@ void ControllerServer::setPlannerPath(const nav_msgs::msg::Path & path)
604
609
throw nav2_core::InvalidPath (" Path is empty." );
605
610
}
606
611
controllers_[current_controller_]->setPlan (path);
607
-
612
+
608
613
end_pose_ = path.poses .back ();
609
614
end_pose_.header .frame_id = path.header .frame_id ;
610
615
goal_checkers_[current_goal_checker_]->reset ();
611
-
616
+
612
617
RCLCPP_DEBUG (
613
618
get_logger (), " Path end point is (%.2f, %.2f)" ,
614
619
end_pose_.pose .position .x , end_pose_.pose .position .y );
615
-
620
+
621
+ start_index_ = 0 ;
616
622
current_path_ = path;
623
+
617
624
}
618
625
619
626
void ControllerServer::computeAndPublishVelocity ()
@@ -750,6 +757,42 @@ void ControllerServer::updateGlobalPath()
750
757
}
751
758
}
752
759
760
+ void ControllerServer::publishTrackingState ()
761
+ {
762
+ if (current_path_.poses .size () < 2 ) {
763
+ RCLCPP_DEBUG (get_logger (), " Path has fewer than 2 points, cannot compute tracking error." );
764
+ return ;
765
+ }
766
+
767
+ geometry_msgs::msg::PoseStamped robot_pose;
768
+ if (!getRobotPose (robot_pose)) {
769
+ RCLCPP_WARN (get_logger (), " Failed to obtain robot pose, skipping tracking error publication." );
770
+ return ;
771
+ }
772
+
773
+ const double distance_to_goal = nav2_util::geometry_utils::euclidean_distance (robot_pose, end_pose_);
774
+ const auto path_search_result = nav2_util::distance_from_path (current_path_, robot_pose.pose , start_index_, search_window_);
775
+ const size_t closest_idx = path_search_result.closest_segment_index ;
776
+ start_index_ = closest_idx;
777
+
778
+ const auto & segment_start = current_path_.poses [closest_idx];
779
+ const auto & segment_end = current_path_.poses [closest_idx + 1 ];
780
+
781
+ double cross_product = nav2_util::geometry_utils::cross_product_2d (
782
+ robot_pose.pose .position , segment_start.pose ,segment_end.pose );
783
+
784
+ nav2_msgs::msg::TrackingError tracking_error_msg;
785
+ tracking_error_msg.header .stamp = now ();
786
+ tracking_error_msg.header .frame_id = robot_pose.header .frame_id ;
787
+ tracking_error_msg.tracking_error = path_search_result.distance ;
788
+ tracking_error_msg.last_index = closest_idx;
789
+ tracking_error_msg.cross_product = cross_product;
790
+ tracking_error_msg.distance_to_goal = distance_to_goal;
791
+ tracking_error_msg.robot_pose = robot_pose;
792
+
793
+ tracking_error_pub_->publish (tracking_error_msg);
794
+ }
795
+
753
796
void ControllerServer::publishVelocity (const geometry_msgs::msg::TwistStamped & velocity)
754
797
{
755
798
auto cmd_vel = std::make_unique<geometry_msgs::msg::TwistStamped>(velocity);
0 commit comments