How to link callback function to a subscription


I have the problem, that my callback function for a subscription is never called. I am mostly using the code from the solution from Exercise 3.2.
Within the MoveBB8_ROS2 class i wanted to create a subscription to the /odom topic to read te data from it. This is, how i have done it so far in my move_bb8.cpp:

The relevant part from the corresponding hpp file lokes like this:

The MoveBB8_ROS2 class is instantiated in the square_service_server.cpp, which looks like this:

Before i start the server, I active the bridge by using the ros2 run ros1_bridge dynamic_bridge --bridge-all-topics command. When I start the server and a client, I can see that the MoveBB8_ROS2 class is created and the robot starts to move. Furthermore i can see that there is a subscriber for the /odom node:

But unfortunately, the MoveBB8_ROS2::odometry_topic_callback method is never called, or at least I get no output from it. I have tried a lot but I just can’t figure out why this does not work. I would be really grateful to hear what I am doing wrong!
Thank you in advance!

Hello @t.zurhelle ,

Could you please upload this code to a rosject? It would make things much easier for us in order to debug the code, and this issue looks like it needs some debugging in order to find out what’s going on.

Hello @albertoezquerro,

thank you for your reply. I uploaded the code to:

I hope I uploaded everything correctly. Please let me know, if I forgot anything.

Hello @t.zurhelle ,

Your problem is that the callback is being blocked by the main thread of the node. To solve these kind of issues you should use Executors and CallbackGroups. We will add these concepts to the course very soon since they are very important in ROS2. In the meantime, here you can have a look at the modifications you need to do to your code in order to have it working.

In the move_bb8.cpp class, I’ve placed the odom callback inside a callback group:

  // Create a Reentrant Callback Group
  auto cbg = this->node_->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
  auto sub1_opt = rclcpp::SubscriptionOptions();
  // Add your callback to the CallbackGroup
  sub1_opt.callback_group = cbg;

  // ROS Subscribers
  this->sub_odometry_ =
          "/odom", 10,
          std::bind(&MoveBB8_ROS2::odometry_topic_callback, this, _1), sub1_opt);

Then, in the square_service_server.cpp file, you need to put your node inside an executor, like this:

int main(int argc, char **argv) {

  rclcpp::init(argc, argv);
  // Create the MultiThreaded executor
  rclcpp::executors::MultiThreadedExecutor executor;

  g_node = rclcpp::Node::make_shared("empty_service_server");
  auto server = g_node->create_service<MyCustomServiceMessage>(
      "/square_service_server", my_handle_service);

  // Add your node to the executor and spin the executor

  return 0;

Hope this helps,

Thank you very much, that’s great, this fully explained and solved the problem!