25 #include "assisted_teleop_behavior_tester.hpp"
26 #include "nav2_util/geometry_utils.hpp"
27 #include "nav2_ros_common/tf2_factories.hpp"
29 using namespace std::chrono_literals;
30 using namespace std::chrono;
32 namespace nav2_system_tests
35 AssistedTeleopBehaviorTester::AssistedTeleopBehaviorTester()
37 initial_pose_received_(false)
39 node_ = rclcpp::Node::make_shared(
40 "assisted_teleop_behavior_test",
41 rclcpp::NodeOptions().parameter_overrides(
42 {rclcpp::Parameter(
"use_sim_time",
true)}));
44 tf_buffer_ = nav2::create_transform_buffer(node_);
45 tf_listener_ = nav2::create_transform_listener(*tf_buffer_);
47 client_ptr_ = rclcpp_action::create_client<AssistedTeleop>(
48 node_->get_node_base_interface(),
49 node_->get_node_graph_interface(),
50 node_->get_node_logging_interface(),
51 node_->get_node_waitables_interface(),
55 node_->create_publisher<geometry_msgs::msg::PoseWithCovarianceStamped>(
"initialpose", 10);
58 node_->create_publisher<std_msgs::msg::Empty>(
"preempt_teleop", 10);
61 node_->create_publisher<geometry_msgs::msg::TwistStamped>(
"cmd_vel_teleop", 10);
63 subscription_ = node_->create_subscription<geometry_msgs::msg::PoseWithCovarianceStamped>(
64 "amcl_pose", rclcpp::QoS(rclcpp::KeepLast(1)).transient_local().reliable(),
65 std::bind(&AssistedTeleopBehaviorTester::amclPoseCallback,
this, std::placeholders::_1));
67 filtered_vel_sub_ = node_->create_subscription<geometry_msgs::msg::TwistStamped>(
69 rclcpp::SystemDefaultsQoS(),
70 std::bind(&AssistedTeleopBehaviorTester::filteredVelCallback,
this, std::placeholders::_1));
72 std::string costmap_topic =
"/local_costmap/costmap_raw";
73 std::string footprint_topic =
"/local_costmap/published_footprint";
75 costmap_sub_ = std::make_shared<nav2_costmap_2d::CostmapSubscriber>(
79 footprint_sub_ = std::make_shared<nav2_costmap_2d::FootprintSubscriber>(
84 collision_checker_ = std::make_unique<nav2_costmap_2d::CostmapTopicCollisionChecker>(
89 stamp_ = node_->now();
90 executor_.add_node(node_);
93 AssistedTeleopBehaviorTester::~AssistedTeleopBehaviorTester()
100 void AssistedTeleopBehaviorTester::activate()
103 throw std::runtime_error(
"Trying to activate while already active");
107 while (!initial_pose_received_) {
108 RCLCPP_WARN(node_->get_logger(),
"Initial pose not received");
110 std::this_thread::sleep_for(100ms);
111 executor_.spin_some();
115 std::this_thread::sleep_for(10s);
118 RCLCPP_ERROR(node_->get_logger(),
"Action client not initialized");
123 if (!client_ptr_->wait_for_action_server(10s)) {
124 RCLCPP_ERROR(node_->get_logger(),
"Action server not available after waiting");
129 RCLCPP_INFO(this->node_->get_logger(),
"Assisted Teleop action server is ready");
133 void AssistedTeleopBehaviorTester::deactivate()
136 throw std::runtime_error(
"Trying to deactivate while already inactive");
141 bool AssistedTeleopBehaviorTester::defaultAssistedTeleopTest(
146 RCLCPP_ERROR(node_->get_logger(),
"Not activated");
150 RCLCPP_INFO(node_->get_logger(),
"Sending goal");
152 auto goal_handle_future = client_ptr_->async_send_goal(nav2_msgs::action::AssistedTeleop::Goal());
154 if (executor_.spin_until_future_complete(goal_handle_future) !=
155 rclcpp::FutureReturnCode::SUCCESS)
157 RCLCPP_ERROR(node_->get_logger(),
"send goal call failed :(");
161 rclcpp_action::ClientGoalHandle<AssistedTeleop>::SharedPtr goal_handle = goal_handle_future.get();
163 RCLCPP_ERROR(node_->get_logger(),
"Goal was rejected by server");
168 auto result_future = client_ptr_->async_get_result(goal_handle);
173 auto start_time = std::chrono::system_clock::now();
174 while (rclcpp::ok()) {
175 geometry_msgs::msg::TwistStamped cmd_vel = geometry_msgs::msg::TwistStamped();
176 cmd_vel.twist.linear.x = lin_vel;
177 cmd_vel.twist.angular.z = ang_vel;
178 cmd_vel_pub_->publish(cmd_vel);
184 auto current_time = std::chrono::system_clock::now();
185 if (current_time - start_time > 25s) {
186 RCLCPP_ERROR(node_->get_logger(),
"Exceeded Timeout");
190 executor_.spin_some();
194 auto preempt_msg = std_msgs::msg::Empty();
195 preempt_pub_->publish(preempt_msg);
197 RCLCPP_INFO(node_->get_logger(),
"Waiting for result");
198 if (executor_.spin_until_future_complete(result_future) !=
199 rclcpp::FutureReturnCode::SUCCESS)
201 RCLCPP_ERROR(node_->get_logger(),
"get result call failed :(");
205 rclcpp_action::ClientGoalHandle<AssistedTeleop>::WrappedResult
206 wrapped_result = result_future.get();
208 switch (wrapped_result.code) {
209 case rclcpp_action::ResultCode::SUCCEEDED:
break;
210 case rclcpp_action::ResultCode::ABORTED: RCLCPP_ERROR(
214 case rclcpp_action::ResultCode::CANCELED: RCLCPP_ERROR(
216 "Goal was canceled");
218 default: RCLCPP_ERROR(node_->get_logger(),
"Unknown result code");
222 RCLCPP_INFO(node_->get_logger(),
"result received");
224 geometry_msgs::msg::PoseStamped current_pose;
225 if (!nav2_util::getCurrentPose(current_pose, *tf_buffer_,
"odom")) {
226 RCLCPP_ERROR(node_->get_logger(),
"Current robot pose is not available.");
230 if (!collision_checker_->isCollisionFree(current_pose.pose)) {
231 RCLCPP_ERROR(node_->get_logger(),
"Ended in collision");
238 void AssistedTeleopBehaviorTester::sendInitialPose()
240 geometry_msgs::msg::PoseWithCovarianceStamped pose;
241 pose.header.frame_id =
"map";
242 pose.header.stamp = stamp_;
243 pose.pose.pose.position.x = -2.0;
244 pose.pose.pose.position.y = -0.5;
245 pose.pose.pose.position.z = 0.0;
246 pose.pose.pose.orientation.x = 0.0;
247 pose.pose.pose.orientation.y = 0.0;
248 pose.pose.pose.orientation.z = 0.0;
249 pose.pose.pose.orientation.w = 1.0;
250 for (
int i = 0; i < 35; i++) {
251 pose.pose.covariance[i] = 0.0;
253 pose.pose.covariance[0] = 0.08;
254 pose.pose.covariance[7] = 0.08;
255 pose.pose.covariance[35] = 0.05;
257 initial_pose_pub_->publish(pose);
258 RCLCPP_INFO(node_->get_logger(),
"Sent initial pose");
261 void AssistedTeleopBehaviorTester::amclPoseCallback(
262 const geometry_msgs::msg::PoseWithCovarianceStamped::ConstSharedPtr)
264 initial_pose_received_ =
true;
267 void AssistedTeleopBehaviorTester::filteredVelCallback(
268 geometry_msgs::msg::TwistStamped::ConstSharedPtr msg)
270 if (msg->twist.linear.x == 0.0f) {