Ask Your Question

Create wall timer using callback with parameters - ROS2, C++

asked 2021-04-06 15:39:26 -0500

mirella melo gravatar image

updated 2021-04-06 15:41:02 -0500

Hi. I have two image msg synchronized as follows:

 message_filters::TimeSynchronizer<Image, Image>  sync(image_1, image_2, 10);
 sync.registerCallback(boost::bind(&callback, _1, _2));

It works until here. Now I'd want to define an interval between triggers of the callback using create_wall_timer. I tried:

 node->create_wall_timer(500ms, boost::bind(&callback, _1, _2));

But I'm getting errors when using it

 error: no matching function for call to ‘rclcpp::Node::create_wall_timer(std::chrono::milliseconds, boost::_bi::bind_t<void, void (*)(const std::shared_ptr<const sensor_msgs::msg::Image_<std::allocator<void> > >&, const std::shared_ptr<const sensor_msgs::msg::Image_<std::allocator<void> > >&), boost::_bi::list2<boost::arg<1>, boost::arg<2> > >)

What would be the proper way to use it? Thanks in advance.

obs: I tried with a callback without parameters node->create_wall_timer(500ms, &callback_test) and it works fine...

obs: alternatives to create_wall_timer are also welcome!

edit retag flag offensive close merge delete

2 Answers

Sort by » oldest newest most voted

answered 2021-04-07 05:38:20 -0500

sgvandijk gravatar image

From your question it seems that you expect that create_wall_timer can be used to specify how often the TimeSynchronizer calls its callback, but that's not the case. The synchronizer will just call its callback as soon as it has two synchronized messages to pass on.

create_wall_timer sets a completely unrelated timer that just calls its callback after the set time. It doesn't know about any topics or events that you may have used the same callback function for. And it does not have any of such information to pass to its callback, so it expects the callback function that you give to take 0 arguments. You pass it one that takes 2, which causes the error: 'there is no matching version of create_wall_timer that can deal with a callback that takes 2 arguments'.

That's why your test with callback_test does work, it takes no arguments, which is what the timer expects.

Side notes:

  • When you only use placeholders, you shouldn't need bind, you should be able to just use sync.registerCallback(&callback). bind is used if you want to use a class method as callback and you have to bind it to this.
  • You can also use lambda's instead of either boost::bind or std::bind, which I personally like better so you don't have to use function pointers or library methods:

    node->create_wall_timer(500ms, []() -> void { callback(); });

    Again here wrapping into a lambda is not strictly necessary and you could just use &callback; you could instead put the logic inside capture() directly into the lambda function, or capture any local variables that can be used at the time the callback is called. For instance as alternative to binding this if callback is a method on your node class:

    node->create_wall_timer(500ms, [this]() -> void { callback(); });
edit flag offensive delete link more

answered 2021-04-06 20:01:27 -0500

ROS2 uses std for bind and most other things that used to use Boost in ROS1. So that line would work as you expect with std::bind.

A practical example in ROS2 can be seen in Nav2's lifecycle manager

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools



Asked: 2021-04-06 15:39:26 -0500

Seen: 23 times

Last updated: Apr 07