ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
4

How to call spin_some or spin_until_future_complete in member functions

asked 2020-06-05 05:44:38 -0500

MrCheesecake gravatar image

updated 2020-06-05 05:48:05 -0500

Hi together,

my coding style of ROS2 is to put all stuff into an object and member functions. Now I wonder how to use spin_some or spin_until_future_complete inside a member function of my object? I tried with this, but that doesn't work.

Here is how I create the object:

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<myNode>());
  rclcpp::shutdown();
  return 0;
}

Example for a service call I want to make:

auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
request->data = true;

auto result = client_->async_send_request(request);
 if (rclcpp::spin_until_future_complete(this, result) != rclcpp::executor::FutureReturnCode::SUCCESS)
{
  RCLCPP_ERROR(this->get_logger(), "Failed");
}
edit retag flag offensive close merge delete

3 Answers

Sort by ยป oldest newest most voted
8

answered 2020-06-05 05:56:49 -0500

MrCheesecake gravatar image

Ok, I did a little bit more of research and had a look into the node class reference here: http://docs.ros2.org/dashing/api/rclc...

I found the function get_node_base_interface() which is what spin_some and spin_until_future_complete need.

example:

auto request = std::make_shared<std_srvs::srv::SetBool::Request>();
request->data = true;

auto result = client_->async_send_request(request);
if (rclcpp::spin_until_future_complete(this->get_node_base_interface(), result) 
    != rclcpp::executor::FutureReturnCode::SUCCESS)
{
  RCLCPP_ERROR(this->get_logger(), "Failed");
}
edit flag offensive delete link more

Comments

Hello,

I recently ended up in a similar design pattern as your answer. Is there any downside to this approach?

Based on the references that I have it is not clear to me whether or not this is a safe pattern to use, or if there are unintended consequences of spinning a node from with in its own member function.

tnz gravatar image tnz  ( 2022-03-03 06:01:14 -0500 )edit

It's ok, it returns a rclcpp::node_interfaces::NodeBaseInterface::SharedPtr needed by the spin_until_future_complete function.
I'm using this solution without problems

dottant gravatar image dottant  ( 2022-04-09 05:20:13 -0500 )edit
1

answered 2022-09-22 02:52:18 -0500

rajmohan747 gravatar image

updated 2022-09-22 02:53:57 -0500

I have also faced a similar challenge during my initial days in ROS2 with C++ OOP,while trying to service call from a member function

Seems like you have both rclcpp::spin and rclcpp::spin_until_future_complete in your code here. This can possibly lead to a race condition

https://github.com/ros2/rclcpp/issues/206

There are multiple possible solutions .Either run your rclcpp::spin in a separate thread

https://gist.github.com/wjwwood/5667039b95a682e3034b

OR

How I have worked around is using the *std::future<t>::get()

auto request = std::make_shared<turtlesim::srv::Spawn::Request>();
request->x = x;
request->y = y;
request->theta = theta;
request->name = name;

RCLCPP_WARN(this->get_logger(), "Spawning '%s'  to '%d'   '%d'", name.c_str(), x, y);
while (!client->wait_for_service(1s))
{
    if (!rclcpp::ok())
    {
        RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
        return;
    }
    RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
}

auto future = client->async_send_request(request);
try
{
    auto response = future.get();
    if (response->name != "")
    {
        RCLCPP_INFO(this->get_logger(), "Turtle %s is now alive.", response->name.c_str());
    }
}
catch (const std::exception &e)
{
    RCLCPP_ERROR(this->get_logger(), "Service call failed.");
}
edit flag offensive delete link more
0

answered 2022-10-06 20:17:19 -0500

Another way is to have a member function set the node as a member variable.

auto node_handle = std::make_shared<...>...); node_handle->setNode(node_handle);

edit flag offensive delete link more

Question Tools

2 followers

Stats

Asked: 2020-06-05 05:44:38 -0500

Seen: 6,919 times

Last updated: Sep 22 '22