0

I have a class where declaration and implementation are in the .cpp file. It has a member function called imageCallback(), used in the constructor as seen below

namespace viso2_ros {

class MonoOdometer : public rclcpp::Node, public OdometerBase
{
MonoOdometer(const std::string& transport, const rclcpp::NodeOptions& options)
  {
    camera_sub_ = image_transport::create_subscription(this, "image", &MonoOdometer::imageCallback, transport, 1);
  }

protected:
  void imageCallback(
      const sensor_msgs::msg::Image::ConstSharedPtr& image_msg) {
      // implementation of the image callback function
    }
}

} // end namespace

To me this looks ok, however it doesn't work.

The create_camera_subscription is expecting this signature for the callback:

const function<void (const shared_ptr<const sensor_msgs::msg::Image_<allocator<void> > > &)>

but it gets this signature

void (viso2_ros::MonoOdometer::*)(const sensor_msgs::msg::Image::ConstSharedPtr &)

What does this signature mean? namespace::classname::pointer ? Why is it not a function?

(the callback signature is the exact same one they use in the documentation https://github.com/ros-perception/image_common/wiki/ROS2-Migration, if interested)

t.niese
  • 39,256
  • 9
  • 74
  • 101
Andreas Klintberg
  • 440
  • 1
  • 11
  • 29

1 Answers1

2

That signature means it is a pointer to a member function rather than a regular pointer to function. In order for MonoOdometer::imageCallback to be called it needs an instance of the class MonoOdometer to call it with, but your create_camera_subscription just expects it to be a standalone function. Two solutions would be to either make imageCallback a static method, or pass a functor (like a lambda) which will call imageCallback in its own call operator.

Static:

static void imageCallback(...) {
  // ...
}

Lambda:

image_transport::create_subscription(this, "image",
  [&](auto& msg) { this->imageCallback(msg); }, transport, 1);
David G
  • 94,763
  • 41
  • 167
  • 253