ros-industrial / industrial_training

ROS-Industrial Training Material
https://industrial-training-master.readthedocs.io
Apache License 2.0
417 stars 234 forks source link

[Docs] Waiting for service response inside an already spinning node is not explained #405

Open PatrickSowinski opened 9 months ago

PatrickSowinski commented 9 months ago

The page about how to wait for a service response inside an already spinning node mentions

There are ways around this limitation but it is beyond the scope of this material.

(see here https://github.com/jdlangs/industrial_training/blob/ros2/gh_pages/_source/session2/ros2/0-Services.md?plain=1#L279C342-L279C342) But it does link to any of these ways. Any idea on where we can find this solution? I've not been able to find anything other than just using callbacks which would not work in every kind of application (e.g. if you want to chain a bunch of service calls after each other).

PatrickSowinski commented 9 months ago

Some forum also mentioned replacing spin() with while True: spin_once() Is that the intended solution that the docs refer to? It seems a bit hacky.

marip8 commented 9 months ago

One way is to use an asynchronous spinner. In ROS2, the equivalent to an async spinner in ROS1 is spinning the node in a separate thread (see here). This allows the node to always be spinning without blocking the "main" thread

rclcpp::executors::multi_threaded_executor::MultiThreadedExecutor executor;
// executor.add_node(...);
std::thread executor_thread(std::bind(&MultiThreadedExecutor::spin, &executor));

// Call service
auto future = service_client->async_send_request(request);

// Do other tasks
...

// Wait for the future to finish and get the response of the service
future.wait();
auto response = future.get();
...

// Once the node is ready to shut down, join the executor thread
executor_thread.join();