25 #include "backup_behavior_tester.hpp"
26 #include "nav2_util/geometry_utils.hpp"
28 using namespace std::chrono_literals;
29 using namespace std::chrono;
31 namespace nav2_system_tests
34 BackupBehaviorTester::BackupBehaviorTester()
36 initial_pose_received_(false)
38 rclcpp::NodeOptions options;
39 options.parameter_overrides({{
"use_sim_time",
true}});
40 node_ = rclcpp::Node::make_shared(
"backup_behavior_test", options);
42 tf_buffer_ = std::make_shared<tf2_ros::Buffer>(node_->get_clock());
43 tf_listener_ = std::make_shared<tf2_ros::TransformListener>(*tf_buffer_);
45 client_ptr_ = rclcpp_action::create_client<BackUp>(
46 node_->get_node_base_interface(),
47 node_->get_node_graph_interface(),
48 node_->get_node_logging_interface(),
49 node_->get_node_waitables_interface(),
53 node_->create_publisher<geometry_msgs::msg::PoseWithCovarianceStamped>(
"initialpose", 10);
55 subscription_ = node_->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>(
56 "amcl_pose", rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable(),
57 std::bind(&BackupBehaviorTester::amclPoseCallback,
this, std::placeholders::_1));
59 stamp_ = node_->now();
62 BackupBehaviorTester::~BackupBehaviorTester()
69 void BackupBehaviorTester::activate()
72 throw std::runtime_error(
"Trying to activate while already active");
76 while (!initial_pose_received_) {
77 RCLCPP_WARN(node_->get_logger(),
"Initial pose not received");
79 std::this_thread::sleep_for(100ms);
80 rclcpp::spin_some(node_);
84 std::this_thread::sleep_for(10s);
87 RCLCPP_ERROR(node_->get_logger(),
"Action client not initialized");
92 if (!client_ptr_->wait_for_action_server(10s)) {
93 RCLCPP_ERROR(node_->get_logger(),
"Action server not available after waiting");
98 RCLCPP_INFO(this->node_->get_logger(),
"Backup action server is ready");
102 void BackupBehaviorTester::deactivate()
105 throw std::runtime_error(
"Trying to deactivate while already inactive");
110 bool BackupBehaviorTester::defaultBackupBehaviorTest(
111 const BackUp::Goal goal_msg,
112 const double tolerance)
115 RCLCPP_ERROR(node_->get_logger(),
"Not activated");
120 std::this_thread::sleep_for(5s);
122 RCLCPP_INFO(this->node_->get_logger(),
"Sending goal");
124 geometry_msgs::msg::PoseStamped initial_pose;
125 if (!nav2_util::getCurrentPose(initial_pose, *tf_buffer_,
"odom")) {
126 RCLCPP_ERROR(node_->get_logger(),
"Current robot pose is not available.");
129 RCLCPP_INFO(node_->get_logger(),
"Found current robot pose");
131 auto goal_handle_future = client_ptr_->async_send_goal(goal_msg);
133 if (rclcpp::spin_until_future_complete(node_, goal_handle_future) !=
134 rclcpp::FutureReturnCode::SUCCESS)
136 RCLCPP_ERROR(node_->get_logger(),
"send goal call failed :(");
140 rclcpp_action::ClientGoalHandle<BackUp>::SharedPtr goal_handle = goal_handle_future.get();
142 RCLCPP_ERROR(node_->get_logger(),
"Goal was rejected by server");
147 auto result_future = client_ptr_->async_get_result(goal_handle);
149 RCLCPP_INFO(node_->get_logger(),
"Waiting for result");
150 if (rclcpp::spin_until_future_complete(node_, result_future) !=
151 rclcpp::FutureReturnCode::SUCCESS)
153 RCLCPP_ERROR(node_->get_logger(),
"get result call failed :(");
157 rclcpp_action::ClientGoalHandle<BackUp>::WrappedResult wrapped_result = result_future.get();
159 switch (wrapped_result.code) {
160 case rclcpp_action::ResultCode::SUCCEEDED:
break;
161 case rclcpp_action::ResultCode::ABORTED: RCLCPP_ERROR(
165 case rclcpp_action::ResultCode::CANCELED: RCLCPP_ERROR(
167 "Goal was canceled");
169 default: RCLCPP_ERROR(node_->get_logger(),
"Unknown result code");
173 RCLCPP_INFO(node_->get_logger(),
"result received");
175 geometry_msgs::msg::PoseStamped current_pose;
176 if (!nav2_util::getCurrentPose(current_pose, *tf_buffer_,
"odom")) {
177 RCLCPP_ERROR(node_->get_logger(),
"Current robot pose is not available.");
181 double dist = nav2_util::geometry_utils::euclidean_distance(initial_pose, current_pose);
183 if (fabs(dist) > fabs(goal_msg.target.x) + tolerance) {
186 "Distance from goal is %lf (tolerance %lf)",
187 fabs(dist - goal_msg.target.x), tolerance);
194 void BackupBehaviorTester::sendInitialPose()
196 geometry_msgs::msg::PoseWithCovarianceStamped pose;
197 pose.header.frame_id =
"map";
198 pose.header.stamp = stamp_;
199 pose.pose.pose.position.x = -2.0;
200 pose.pose.pose.position.y = -0.5;
201 pose.pose.pose.position.z = 0.0;
202 pose.pose.pose.orientation.x = 0.0;
203 pose.pose.pose.orientation.y = 0.0;
204 pose.pose.pose.orientation.z = 0.0;
205 pose.pose.pose.orientation.w = 1.0;
206 for (
int i = 0; i < 35; i++) {
207 pose.pose.covariance[i] = 0.0;
209 pose.pose.covariance[0] = 0.08;
210 pose.pose.covariance[7] = 0.08;
211 pose.pose.covariance[35] = 0.05;
213 publisher_->publish(pose);
214 RCLCPP_INFO(node_->get_logger(),
"Sent initial pose");
217 void BackupBehaviorTester::amclPoseCallback(
218 const geometry_msgs::msg::PoseWithCovarianceStamped::SharedPtr)
220 initial_pose_received_ =
true;