Return code for spin_until_future_complete
This commit is contained in:
parent
8de48c5c0d
commit
2d840a5f3a
3 changed files with 83 additions and 16 deletions
|
@ -29,20 +29,56 @@ namespace executors
|
||||||
using rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor;
|
using rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor;
|
||||||
using rclcpp::executors::single_threaded_executor::SingleThreadedExecutor;
|
using rclcpp::executors::single_threaded_executor::SingleThreadedExecutor;
|
||||||
|
|
||||||
template<typename FutureT>
|
/// Return codes to be used with spin_until_future_complete.
|
||||||
std::shared_future<FutureT> &
|
/**
|
||||||
|
* SUCCESS: The future is complete and can be accessed with "get" without blocking.
|
||||||
|
* INTERRUPTED: The future is not complete, spinning was interrupted by Ctrl-C or another error.
|
||||||
|
* TIMEOUT: Spinning timed out.
|
||||||
|
*/
|
||||||
|
enum FutureReturnCode {SUCCESS, INTERRUPTED, TIMEOUT};
|
||||||
|
|
||||||
|
/// Spin (blocking) until the future is complete, until the function times out (if applicable),
|
||||||
|
/// or until rclcpp is interrupted.
|
||||||
|
/**
|
||||||
|
* \param[in] executor The executor which will spin the node.
|
||||||
|
* \param[in] node_ptr The node to spin.
|
||||||
|
* \param[in] future The future to wait on. If SUCCESS, the future is safe to access after this function
|
||||||
|
* \param[in] timeout Optional timeout parameter, which gets passed to Executor::spin_node_once.
|
||||||
|
-1 is block forever, 0 is non-blocking.
|
||||||
|
If the time spent inside the blocking loop exceeds this timeout, return a TIMEOUT return code.
|
||||||
|
* \return The return code, one of SUCCESS, INTERRUPTED, or TIMEOUT.
|
||||||
|
*/
|
||||||
|
template<typename ResponseT, typename TimeT = std::milli>
|
||||||
|
FutureReturnCode
|
||||||
spin_node_until_future_complete(
|
spin_node_until_future_complete(
|
||||||
rclcpp::executor::Executor & executor, rclcpp::node::Node::SharedPtr node_ptr,
|
rclcpp::executor::Executor & executor, rclcpp::node::Node::SharedPtr node_ptr,
|
||||||
std::shared_future<FutureT> & future)
|
std::shared_future<ResponseT> & future,
|
||||||
|
std::chrono::duration<int64_t, TimeT> timeout = std::chrono::duration<int64_t, TimeT>(-1))
|
||||||
{
|
{
|
||||||
std::future_status status;
|
|
||||||
// TODO(wjwwood): does not work recursively right, can't call spin_node_until_future_complete
|
// TODO(wjwwood): does not work recursively right, can't call spin_node_until_future_complete
|
||||||
// inside a callback executed by an executor.
|
// inside a callback executed by an executor.
|
||||||
do {
|
|
||||||
executor.spin_node_once(node_ptr);
|
// Check the future before entering the while loop.
|
||||||
|
// If the future is already complete, don't try to spin.
|
||||||
|
std::future_status status = future.wait_for(std::chrono::seconds(0));
|
||||||
|
|
||||||
|
auto start_time = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
while (status != std::future_status::ready && rclcpp::utilities::ok()) {
|
||||||
|
executor.spin_node_once(node_ptr, timeout);
|
||||||
|
if (timeout.count() >= 0) {
|
||||||
|
if (start_time + timeout < std::chrono::system_clock::now()) {
|
||||||
|
return TIMEOUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
status = future.wait_for(std::chrono::seconds(0));
|
status = future.wait_for(std::chrono::seconds(0));
|
||||||
} while (status != std::future_status::ready && rclcpp::utilities::ok());
|
}
|
||||||
return future;
|
|
||||||
|
// If the future completed, and we weren't interrupted by ctrl-C, return the response
|
||||||
|
if (status == std::future_status::ready) {
|
||||||
|
return FutureReturnCode::SUCCESS;
|
||||||
|
}
|
||||||
|
return FutureReturnCode::INTERRUPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace executors
|
} // namespace executors
|
||||||
|
|
|
@ -274,28 +274,53 @@ public:
|
||||||
get_parameters(std::vector<std::string> parameter_names)
|
get_parameters(std::vector<std::string> parameter_names)
|
||||||
{
|
{
|
||||||
auto f = async_parameters_client_->get_parameters(parameter_names);
|
auto f = async_parameters_client_->get_parameters(parameter_names);
|
||||||
return rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f).get();
|
if (rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f) ==
|
||||||
|
rclcpp::executors::FutureReturnCode::SUCCESS)
|
||||||
|
{
|
||||||
|
return f.get();
|
||||||
|
}
|
||||||
|
// Return an empty vector if unsuccessful
|
||||||
|
return std::vector<rclcpp::parameter::ParameterVariant>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rclcpp::parameter::ParameterType>
|
std::vector<rclcpp::parameter::ParameterType>
|
||||||
get_parameter_types(std::vector<std::string> parameter_names)
|
get_parameter_types(std::vector<std::string> parameter_names)
|
||||||
{
|
{
|
||||||
auto f = async_parameters_client_->get_parameter_types(parameter_names);
|
auto f = async_parameters_client_->get_parameter_types(parameter_names);
|
||||||
return rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f).get();
|
|
||||||
|
if (rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f) ==
|
||||||
|
rclcpp::executors::FutureReturnCode::SUCCESS)
|
||||||
|
{
|
||||||
|
return f.get();
|
||||||
|
}
|
||||||
|
return std::vector<rclcpp::parameter::ParameterType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<rcl_interfaces::msg::SetParametersResult>
|
std::vector<rcl_interfaces::msg::SetParametersResult>
|
||||||
set_parameters(std::vector<rclcpp::parameter::ParameterVariant> parameters)
|
set_parameters(std::vector<rclcpp::parameter::ParameterVariant> parameters)
|
||||||
{
|
{
|
||||||
auto f = async_parameters_client_->set_parameters(parameters);
|
auto f = async_parameters_client_->set_parameters(parameters);
|
||||||
return rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f).get();
|
|
||||||
|
if (rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f) ==
|
||||||
|
rclcpp::executors::FutureReturnCode::SUCCESS)
|
||||||
|
{
|
||||||
|
return f.get();
|
||||||
|
}
|
||||||
|
return std::vector<rcl_interfaces::msg::SetParametersResult>();
|
||||||
}
|
}
|
||||||
|
|
||||||
rcl_interfaces::msg::SetParametersResult
|
rcl_interfaces::msg::SetParametersResult
|
||||||
set_parameters_atomically(std::vector<rclcpp::parameter::ParameterVariant> parameters)
|
set_parameters_atomically(std::vector<rclcpp::parameter::ParameterVariant> parameters)
|
||||||
{
|
{
|
||||||
auto f = async_parameters_client_->set_parameters_atomically(parameters);
|
auto f = async_parameters_client_->set_parameters_atomically(parameters);
|
||||||
return rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f).get();
|
|
||||||
|
if (rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f) ==
|
||||||
|
rclcpp::executors::FutureReturnCode::SUCCESS)
|
||||||
|
{
|
||||||
|
return f.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Unable to get result of set parameters service call.");
|
||||||
}
|
}
|
||||||
|
|
||||||
rcl_interfaces::msg::ListParametersResult
|
rcl_interfaces::msg::ListParametersResult
|
||||||
|
@ -304,7 +329,14 @@ public:
|
||||||
uint64_t depth)
|
uint64_t depth)
|
||||||
{
|
{
|
||||||
auto f = async_parameters_client_->list_parameters(parameter_prefixes, depth);
|
auto f = async_parameters_client_->list_parameters(parameter_prefixes, depth);
|
||||||
return rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f).get();
|
|
||||||
|
if (rclcpp::executors::spin_node_until_future_complete(*executor_, node_, f) ==
|
||||||
|
rclcpp::executors::FutureReturnCode::SUCCESS)
|
||||||
|
{
|
||||||
|
return f.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error("Unable to get result of list parameters service call.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FunctorT>
|
template<typename FunctorT>
|
||||||
|
|
|
@ -98,14 +98,13 @@ void spin(Node::SharedPtr node_ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FutureT>
|
template<typename FutureT>
|
||||||
std::shared_future<FutureT> &
|
rclcpp::executors::FutureReturnCode
|
||||||
spin_until_future_complete(
|
spin_until_future_complete(
|
||||||
Node::SharedPtr node_ptr, std::shared_future<FutureT> & future)
|
Node::SharedPtr node_ptr, std::shared_future<FutureT> & future)
|
||||||
{
|
{
|
||||||
rclcpp::executors::SingleThreadedExecutor executor;
|
rclcpp::executors::SingleThreadedExecutor executor;
|
||||||
rclcpp::executors::spin_node_until_future_complete<FutureT>(
|
return rclcpp::executors::spin_node_until_future_complete<FutureT>(
|
||||||
executor, node_ptr, future);
|
executor, node_ptr, future);
|
||||||
return future;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace rclcpp */
|
} /* namespace rclcpp */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue