Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rclcpp_action] Action client implementation #594

Merged
merged 56 commits into from
Dec 5, 2018
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
ecf8b5f
WIP
hidmic Nov 20, 2018
ad227d4
Added basic waitable interface to action client
sservulo Nov 26, 2018
584ab25
Updated waitable execute from action client
sservulo Nov 26, 2018
e221967
Added throw for rcl calls in action client
sservulo Nov 26, 2018
ce1b068
Removed duplicated ready flags from action client
sservulo Nov 26, 2018
ffcb8bb
Minor fix
sservulo Nov 26, 2018
d888fd5
Added header to action ClientBaseImpl execute
sservulo Nov 26, 2018
440ee03
Mich's update to action client interface
sservulo Nov 27, 2018
0c7dfd8
Removed async_cancel from action ClintGoalHandle API
sservulo Nov 22, 2018
a94ca35
Added status handler to action client goal handler
sservulo Nov 22, 2018
7fbb253
Added result handler to action client goal handler
sservulo Nov 22, 2018
1a1f79a
Identation fix
sservulo Nov 22, 2018
17a7a8d
Added get/set for action client goal handler
sservulo Nov 22, 2018
bcf1553
Changed action client goal handler attrs from rcl to cpp versions
sservulo Nov 22, 2018
5b2bc4c
Added check methods to action client goal handler
sservulo Nov 22, 2018
6b3482f
Removed rcl_client pointer from action client goal handler
sservulo Nov 22, 2018
5967df8
Added trailing suffix to client pimpl attrs
sservulo Nov 27, 2018
58215f3
Towards a consistent action client
hidmic Nov 28, 2018
1e9d56e
Misc fixes for the action client
hidmic Nov 28, 2018
5ec7562
Yet more misc fixes for the action client
hidmic Nov 28, 2018
68a2e17
Few more fixes and shortcuts to deal with missing type support.
hidmic Nov 28, 2018
4275ce7
Fixed lint errors in action headers and client
hidmic Nov 29, 2018
9545a0b
Fixes to action client internal workflow.
hidmic Nov 29, 2018
ab5df90
Misc fixes to get client example to build
sloretz Nov 30, 2018
4825f95
More misck client fixes
sloretz Nov 30, 2018
f04a50e
Remove debug print
sloretz Nov 30, 2018
750e19b
replace logging with throw_from_rcl_error
sloretz Dec 1, 2018
af831b3
Wrap result object given by client to user
sloretz Dec 1, 2018
da9d530
Fix a couple bugs trying to cancel goals
sloretz Dec 1, 2018
65fa041
Use unique_indentifier_msgs
sloretz Dec 4, 2018
2faa4b7
create_client accepts group and removes waitable
sloretz Dec 4, 2018
7fa9a14
Uncrustify fixes
sloretz Dec 4, 2018
7c2c69e
[rclcpp_action] Adds tests for action client.
sservulo Nov 28, 2018
927115c
[WIP] Failing action client tests.
hidmic Dec 5, 2018
c2c6775
[rclcpp_action] Action client tests passing.
hidmic Dec 5, 2018
ed1af61
Spin both executors to make tests pass on my machine
sloretz Dec 5, 2018
923564b
Feedback callback uses shared pointer
sloretz Dec 5, 2018
9e74ca4
comment about why make_result_aware is called
sloretz Dec 5, 2018
f7a52eb
Client documentation
sloretz Dec 5, 2018
8b173d5
Execute one thing at a time
sloretz Dec 5, 2018
f1ed490
Return nullptr instead of throwing RejectedGoalError
sloretz Dec 5, 2018
4dc00d9
ClientGoalHandle worries about feedback awareness
sloretz Dec 5, 2018
7489e75
cpplint + uncrustify
sloretz Dec 5, 2018
f2dc2ab
Use node logging interface
sloretz Dec 5, 2018
8e0da8f
ACTION -> ActionT
sloretz Dec 5, 2018
62c27a4
Make ClientBase constructor protected
sloretz Dec 5, 2018
cc2d038
Return types on different line
sloretz Dec 5, 2018
5797e51
Avoid passing const reference to temporary
sloretz Dec 5, 2018
df0a3fa
Child logger rclcpp_action
sloretz Dec 5, 2018
fa391a1
Child logger rclcpp_action
sloretz Dec 5, 2018
175213e
possible windows fixes
sloretz Dec 5, 2018
7cb39d8
remove excess space
sloretz Dec 5, 2018
05cfd8e
swap argument order
sloretz Dec 5, 2018
9b63b47
Misc test additions
sloretz Dec 5, 2018
a4b1cb4
Windows independent_bits_engine can't do uint8_t
sloretz Dec 5, 2018
ffa4dce
Windows link issues
sloretz Dec 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
243 changes: 164 additions & 79 deletions rclcpp_action/include/rclcpp_action/client.hpp

Large diffs are not rendered by default.

28 changes: 18 additions & 10 deletions rclcpp_action/include/rclcpp_action/client_goal_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <action_msgs/msg/goal_status.hpp>
#include <rclcpp/macros.hpp>
#include <rclcpp/time.hpp>

#include <functional>
#include <future>
Expand All @@ -41,10 +42,10 @@ enum class ResultCode : int8_t


// Forward declarations
template<typename ACTION>
template<typename ActionT>
class Client;

template<typename ACTION>
template<typename ActionT>
class ClientGoalHandle
{
public:
Expand All @@ -58,22 +59,24 @@ class ClientGoalHandle
/// A status to indicate if the goal was canceled, aborted, or suceeded
ResultCode code;
/// User defined fields sent back with an action
typename ACTION::Result::SharedPtr response;
typename ActionT::Result::SharedPtr response;
} Result;

using Feedback = typename ACTION::Feedback;
using FeedbackCallback = std::function<void (ClientGoalHandle::SharedPtr, const Feedback &)>;
using Feedback = typename ActionT::Feedback;
using FeedbackCallback =
std::function<void (ClientGoalHandle::SharedPtr, const std::shared_ptr<const Feedback>)>;

virtual ~ClientGoalHandle();

const GoalID & get_goal_id() const;
const GoalID &
get_goal_id() const;

rclcpp::Time
get_goal_stamp() const;

std::shared_future<Result>
async_result();

FeedbackCallback
get_feedback_callback();

int8_t
get_status();

Expand All @@ -85,13 +88,18 @@ class ClientGoalHandle

private:
// The templated Client creates goal handles
friend Client<ACTION>;
friend Client<ActionT>;

ClientGoalHandle(const GoalInfo & info, FeedbackCallback callback);

void
set_feedback_callback(FeedbackCallback callback);

void
call_feedback_callback(
ClientGoalHandle<ActionT>::SharedPtr shared_this,
typename std::shared_ptr<const Feedback> feedback_message);

void
set_result_awareness(bool awareness);

Expand Down
87 changes: 54 additions & 33 deletions rclcpp_action/include/rclcpp_action/client_goal_handle_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,44 @@

#include <rcl_action/types.h>

#include <memory>

#include "rclcpp_action/exceptions.hpp"

namespace rclcpp_action
{

template<typename ACTION>
ClientGoalHandle<ACTION>::ClientGoalHandle(
template<typename ActionT>
ClientGoalHandle<ActionT>::ClientGoalHandle(
const GoalInfo & info, FeedbackCallback callback)
: info_(info), result_future_(result_promise_.get_future()), feedback_callback_(callback)
{
}

template<typename ACTION>
ClientGoalHandle<ACTION>::~ClientGoalHandle()
template<typename ActionT>
ClientGoalHandle<ActionT>::~ClientGoalHandle()
{
}

template<typename ACTION>
template<typename ActionT>
const GoalID &
ClientGoalHandle<ACTION>::get_goal_id() const
ClientGoalHandle<ActionT>::get_goal_id() const
{
// return info_.goal_id;
return info_.goal_id.uuid;
}

template<typename ACTION>
std::shared_future<typename ClientGoalHandle<ACTION>::Result>
ClientGoalHandle<ACTION>::async_result()
template<typename ActionT>
rclcpp::Time
ClientGoalHandle<ActionT>::get_goal_stamp() const
{
return info_.stamp;
}


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excess space

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

template<typename ActionT>
std::shared_future<typename ClientGoalHandle<ActionT>::Result>
ClientGoalHandle<ActionT>::async_result()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
if (!is_result_aware_) {
Expand All @@ -53,81 +63,92 @@ ClientGoalHandle<ACTION>::async_result()
return result_future_;
}

template<typename ACTION>
template<typename ActionT>
void
ClientGoalHandle<ACTION>::set_result(const Result & result)
ClientGoalHandle<ActionT>::set_result(const Result & result)
{
std::lock_guard<std::mutex> guard(handle_mutex_);
status_ = static_cast<int8_t>(result.code);
result_promise_.set_value(result);
}

template<typename ACTION>
typename ClientGoalHandle<ACTION>::FeedbackCallback
ClientGoalHandle<ACTION>::get_feedback_callback()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
return feedback_callback_;
}

template<typename ACTION>
template<typename ActionT>
void
ClientGoalHandle<ACTION>::set_feedback_callback(FeedbackCallback callback)
ClientGoalHandle<ActionT>::set_feedback_callback(FeedbackCallback callback)
{
std::lock_guard<std::mutex> guard(handle_mutex_);
feedback_callback_ = callback;
}

template<typename ACTION>
template<typename ActionT>
int8_t
ClientGoalHandle<ACTION>::get_status()
ClientGoalHandle<ActionT>::get_status()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
return status_;
}

template<typename ACTION>
template<typename ActionT>
void
ClientGoalHandle<ACTION>::set_status(int8_t status)
ClientGoalHandle<ActionT>::set_status(int8_t status)
{
std::lock_guard<std::mutex> guard(handle_mutex_);
status_ = status;
}

template<typename ACTION>
template<typename ActionT>
bool
ClientGoalHandle<ACTION>::is_feedback_aware()
ClientGoalHandle<ActionT>::is_feedback_aware()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
return feedback_callback_ != nullptr;
}

template<typename ACTION>
template<typename ActionT>
bool
ClientGoalHandle<ACTION>::is_result_aware()
ClientGoalHandle<ActionT>::is_result_aware()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
return is_result_aware_;
}

template<typename ACTION>
template<typename ActionT>
void
ClientGoalHandle<ACTION>::set_result_awareness(bool awareness)
ClientGoalHandle<ActionT>::set_result_awareness(bool awareness)
{
std::lock_guard<std::mutex> guard(handle_mutex_);
is_result_aware_ = awareness;
}

template<typename ACTION>
template<typename ActionT>
void
ClientGoalHandle<ACTION>::invalidate()
ClientGoalHandle<ActionT>::invalidate()
{
std::lock_guard<std::mutex> guard(handle_mutex_);
status_ = GoalStatus::STATUS_UNKNOWN;
result_promise_.set_exception(std::make_exception_ptr(
exceptions::UnawareGoalHandleError()));
}

template<typename ActionT>
void
ClientGoalHandle<ActionT>::call_feedback_callback(
ClientGoalHandle<ActionT>::SharedPtr shared_this,
typename std::shared_ptr<const Feedback> feedback_message)
{
if (shared_this.get() != this) {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp_action"), "Sent feedback to wrong goal handle.");
return;
}
std::lock_guard<std::mutex> guard(handle_mutex_);
if (feedback_callback_ == nullptr) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (feedback_callback_ == nullptr) {
if (nullptr == feedback_callback_) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Normal, some feedback messages may arrive after the goal result.
RCLCPP_DEBUG(rclcpp::get_logger("rclcpp_action"), "Received feedback but goal ignores it.");
return;
}
feedback_callback_(shared_this, feedback_message);
}

} // namespace rclcpp_action

#endif // RCLCPP_ACTION__CLIENT_GOAL_HANDLE_IMPL_HPP_
13 changes: 7 additions & 6 deletions rclcpp_action/include/rclcpp_action/create_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

namespace rclcpp_action
{
template<typename ACTION>
typename Client<ACTION>::SharedPtr
template<typename ActionT>
typename Client<ActionT>::SharedPtr
create_client(
rclcpp::Node::SharedPtr node,
const std::string & name,
Expand All @@ -37,7 +37,7 @@ create_client(
std::weak_ptr<rclcpp::callback_group::CallbackGroup> weak_group = group;
bool group_is_null = (nullptr == group.get());

auto deleter = [weak_node, weak_group, group_is_null](Client<ACTION> * ptr)
auto deleter = [weak_node, weak_group, group_is_null](Client<ActionT> * ptr)
{
if (nullptr == ptr) {
return;
Expand All @@ -47,7 +47,7 @@ create_client(
return;
}
// API expects a shared pointer, give it one with a deleter that does nothing.
std::shared_ptr<Client<ACTION>> fake_shared_ptr(ptr, [](Client<ACTION> *) {});
std::shared_ptr<Client<ActionT>> fake_shared_ptr(ptr, [](Client<ActionT> *) {});

if (group_is_null) {
// Was added to default group
Expand All @@ -62,8 +62,9 @@ create_client(
delete ptr;
};

std::shared_ptr<Client<ACTION>> action_client(
new Client<ACTION>(node->get_node_base_interface(), name), deleter);
std::shared_ptr<Client<ActionT>> action_client(
new Client<ActionT>(node->get_node_base_interface(), node->get_node_logging_interface(), name),
deleter);

node->get_node_waitables_interface()->add_waitable(action_client, group);
return action_client;
Expand Down
14 changes: 2 additions & 12 deletions rclcpp_action/include/rclcpp_action/exceptions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,11 @@ namespace rclcpp_action
{
namespace exceptions
{

class RejectedGoalError : public std::runtime_error
{
public:
RejectedGoalError()
: std::runtime_error("")
{
}
};

class UnknownGoalHandleError : public std::invalid_argument
{
public:
UnknownGoalHandleError()
: std::invalid_argument("")
: std::invalid_argument("Goal handle is not know to this client.")
{
}
};
Expand All @@ -44,7 +34,7 @@ class UnawareGoalHandleError : public std::runtime_error
{
public:
UnawareGoalHandleError()
: std::runtime_error("")
: std::runtime_error("Goal handle is not tracking the goal result.")
{
}
};
Expand Down
11 changes: 5 additions & 6 deletions rclcpp_action/include/rclcpp_action/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@

namespace rclcpp_action
{
// using GoalID = unique_identifier_msgs::msg::UUID;
using GoalID = std::array<uint8_t, 16>;

using GoalID = std::array<uint8_t, UUID_SIZE>;
using GoalStatus = action_msgs::msg::GoalStatus;
using GoalInfo = action_msgs::msg::GoalInfo;

Expand All @@ -38,11 +38,10 @@ template<>
struct less<rclcpp_action::GoalID>
{
bool operator()(
const rclcpp_action::GoalID & id0,
const rclcpp_action::GoalID & id1) const
const rclcpp_action::GoalID & lhs,
const rclcpp_action::GoalID & rhs) const
{
// return (id0.uuid < id1.uuid);
return id0 < id1;
return lhs < rhs;
}
};
} // namespace std
Expand Down
Loading