Use options struct for passing callbacks to async_send_goal
Now supports callbacks for the goal response and result. This also makes it easier to incorporate action clients in composable nodes since we don't have to rely on waiting on futures. Signed-off-by: Jacob Perron <jacob@openrobotics.org>
This commit is contained in:
parent
6b10841477
commit
0da966b981
4 changed files with 151 additions and 30 deletions
|
@ -268,20 +268,20 @@ TEST_F(TestClient, construction_and_destruction)
|
|||
ASSERT_NO_THROW(rclcpp_action::create_client<ActionType>(client_node, action_name).reset());
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_send_goal_but_ignore_feedback_and_result)
|
||||
TEST_F(TestClient, async_send_goal_no_callbacks)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal bad_goal;
|
||||
bad_goal.order = -5;
|
||||
auto future_goal_handle = action_client->async_send_goal(bad_goal, nullptr, true);
|
||||
auto future_goal_handle = action_client->async_send_goal(bad_goal);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
EXPECT_EQ(nullptr, future_goal_handle.get().get());
|
||||
|
||||
ActionGoal good_goal;
|
||||
good_goal.order = 5;
|
||||
future_goal_handle = action_client->async_send_goal(good_goal, nullptr, true);
|
||||
future_goal_handle = action_client->async_send_goal(good_goal);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
|
@ -290,7 +290,7 @@ TEST_F(TestClient, async_send_goal_but_ignore_feedback_and_result)
|
|||
EXPECT_THROW(goal_handle->async_result(), rclcpp_action::exceptions::UnawareGoalHandleError);
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_send_goal_and_ignore_feedback_but_wait_for_result)
|
||||
TEST_F(TestClient, async_send_goal_no_callbacks_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
@ -302,8 +302,9 @@ TEST_F(TestClient, async_send_goal_and_ignore_feedback_but_wait_for_result)
|
|||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_FALSE(goal_handle->is_feedback_aware());
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
auto future_result = goal_handle->async_result();
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
ASSERT_EQ(6ul, wrapped_result.result->sequence.size());
|
||||
|
@ -312,7 +313,41 @@ TEST_F(TestClient, async_send_goal_and_ignore_feedback_but_wait_for_result)
|
|||
EXPECT_EQ(5, wrapped_result.result->sequence[5]);
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_send_goal_with_feedback_and_result)
|
||||
TEST_F(TestClient, async_send_goal_with_goal_response_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
goal.order = 4;
|
||||
bool goal_response_received = false;
|
||||
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions();
|
||||
send_goal_ops.goal_response_callback =
|
||||
[&goal_response_received]
|
||||
(std::shared_future<typename ActionGoalHandle::SharedPtr> future) mutable
|
||||
{
|
||||
auto goal_handle = future.get();
|
||||
if (goal_handle) {
|
||||
goal_response_received = true;
|
||||
}
|
||||
};
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_TRUE(goal_response_received);
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_FALSE(goal_handle->is_feedback_aware());
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
|
||||
ASSERT_EQ(5u, wrapped_result.result->sequence.size());
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_send_goal_with_feedback_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
@ -320,22 +355,24 @@ TEST_F(TestClient, async_send_goal_with_feedback_and_result)
|
|||
ActionGoal goal;
|
||||
goal.order = 4;
|
||||
int feedback_count = 0;
|
||||
auto future_goal_handle = action_client->async_send_goal(
|
||||
goal,
|
||||
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions();
|
||||
send_goal_ops.feedback_callback =
|
||||
[&feedback_count](
|
||||
typename ActionGoalHandle::SharedPtr goal_handle,
|
||||
const std::shared_ptr<const ActionFeedback> feedback) mutable
|
||||
typename ActionGoalHandle::SharedPtr goal_handle,
|
||||
const std::shared_ptr<const ActionFeedback> feedback) mutable
|
||||
{
|
||||
(void)goal_handle;
|
||||
(void)feedback;
|
||||
feedback_count++;
|
||||
});
|
||||
};
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_TRUE(goal_handle->is_feedback_aware());
|
||||
EXPECT_FALSE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
auto future_result = goal_handle->async_result();
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
|
||||
|
@ -344,6 +381,40 @@ TEST_F(TestClient, async_send_goal_with_feedback_and_result)
|
|||
EXPECT_EQ(5, feedback_count);
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_send_goal_with_result_callback_wait_for_result)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
ASSERT_TRUE(action_client->wait_for_action_server(WAIT_FOR_SERVER_TIMEOUT));
|
||||
|
||||
ActionGoal goal;
|
||||
goal.order = 4;
|
||||
bool result_callback_received = false;
|
||||
auto send_goal_ops = rclcpp_action::Client<ActionType>::SendGoalOptions();
|
||||
send_goal_ops.result_callback =
|
||||
[&result_callback_received](
|
||||
const typename ActionGoalHandle::WrappedResult & result) mutable
|
||||
{
|
||||
if (rclcpp_action::ResultCode::SUCCEEDED == result.code &&
|
||||
result.result->sequence.size() == 5u)
|
||||
{
|
||||
result_callback_received = true;
|
||||
}
|
||||
};
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, send_goal_ops);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
EXPECT_FALSE(goal_handle->is_feedback_aware());
|
||||
EXPECT_TRUE(goal_handle->is_result_aware());
|
||||
auto future_result = action_client->async_get_result(goal_handle);
|
||||
dual_spin_until_future_complete(future_result);
|
||||
auto wrapped_result = future_result.get();
|
||||
|
||||
EXPECT_TRUE(result_callback_received);
|
||||
ASSERT_EQ(5u, wrapped_result.result->sequence.size());
|
||||
EXPECT_EQ(3, wrapped_result.result->sequence.back());
|
||||
}
|
||||
|
||||
TEST_F(TestClient, async_cancel_one_goal)
|
||||
{
|
||||
auto action_client = rclcpp_action::create_client<ActionType>(client_node, action_name);
|
||||
|
@ -351,7 +422,7 @@ TEST_F(TestClient, async_cancel_one_goal)
|
|||
|
||||
ActionGoal goal;
|
||||
goal.order = 5;
|
||||
auto future_goal_handle = action_client->async_send_goal(goal, nullptr, true);
|
||||
auto future_goal_handle = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle);
|
||||
auto goal_handle = future_goal_handle.get();
|
||||
EXPECT_EQ(rclcpp_action::GoalStatus::STATUS_ACCEPTED, goal_handle->get_status());
|
||||
|
@ -369,14 +440,14 @@ TEST_F(TestClient, async_cancel_all_goals)
|
|||
|
||||
ActionGoal goal;
|
||||
goal.order = 6;
|
||||
auto future_goal_handle0 = action_client->async_send_goal(goal, nullptr, true);
|
||||
auto future_goal_handle0 = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle0);
|
||||
auto goal_handle0 = future_goal_handle0.get();
|
||||
|
||||
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(2)));
|
||||
|
||||
goal.order = 8;
|
||||
auto future_goal_handle1 = action_client->async_send_goal(goal, nullptr, true);
|
||||
auto future_goal_handle1 = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle1);
|
||||
auto goal_handle1 = future_goal_handle1.get();
|
||||
|
||||
|
@ -404,14 +475,14 @@ TEST_F(TestClient, async_cancel_some_goals)
|
|||
|
||||
ActionGoal goal;
|
||||
goal.order = 6;
|
||||
auto future_goal_handle0 = action_client->async_send_goal(goal, nullptr, true);
|
||||
auto future_goal_handle0 = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle0);
|
||||
auto goal_handle0 = future_goal_handle0.get();
|
||||
|
||||
ASSERT_EQ(RCL_RET_OK, rcl_set_ros_time_override(clock.get_clock_handle(), RCL_S_TO_NS(2)));
|
||||
|
||||
goal.order = 8;
|
||||
auto future_goal_handle1 = action_client->async_send_goal(goal, nullptr, true);
|
||||
auto future_goal_handle1 = action_client->async_send_goal(goal);
|
||||
dual_spin_until_future_complete(future_goal_handle1);
|
||||
auto goal_handle1 = future_goal_handle1.get();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue