title: Pass non-static class member callback function to ros::subscriber
body: <p>I'm trying to write a class that handles motor control stuff for a ROS-based robot (specifically for an ESP32 chip using the Arduino IDE).</p>
  <p>For this I want to implement a ROS-serial subscriber, that calls a callback function whenever a new message is received. The callback function stores the message data in an instance variable of the class, so I can easily work with it with other functions of the class.</p>
  <p>This makes the callback function non static, therefore I used <code>std::bind</code> to bind it to the specific instance of my class while keeping a placeholder for the message.</p>
  <p>A simplified code example:</p>
  <pre><code>#include &lt;ros.h&gt;
  #include &lt;geometry_msgs/Twist.h&gt;
  
  ros::NodeHandle nh;
  
  const char cmd_vel_topic[] = &quot;/cmd_vel&quot;
  
  class MotorControlInterface {
  
    public:
      // FreeRTOS task to call from main
      void TaskMotorControl(void *pvParameters)
      {    
        ros::Subscriber&lt;geometry_msgs::Twist&gt; twist_sub
        ( 
            // The topic to subscribe to
            cmd_vel_topic,
            // Reference to callback function that is bound to this instance of the class
            &amp;std::bind(&amp;MotorControlInterface::twistCallback, this, std::placeholders::_1),             
        );
        nh.subscribe(twist_sub);
        
        for(;;)
        {
          // Do some stuff with velocity commands
          handleMotorSpeeds();
          vTaskDelay( 10 );
        }
      };
  
    private:
      // Instance variable I want to store message data in
      double vel_cmd_x;
  
      // Callback function 
      void twistCallback(const geometry_msgs::Twist&amp; twist_msg)
      {
        // Save velocity command
        vel_cmd_x = twist_msg.linear.x;
      };
  
  };
  </code></pre>
  <p>The error message I get:</p>
  <pre><code>Arduino: 1.8.15 (Linux), Board: &quot;ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 921600, None&quot;
  
  
  /home/ubuntu/Arduino/***/*****.ino: In member function 'void MotorControlInterface::TaskMotorControl(void*)':
  *****:83:87: error: taking address of temporary [-fpermissive]
           &amp;std::bind( &amp;MotorControlInterface::twistCallback, this, std::placeholders::_1)
                                                                                         ^
  *****:84:7: error: no matching function for call to 'ros::Subscriber&lt;geometry_msgs::Twist&gt;::Subscriber(const char [9], std::_Bind_helper&lt;false, void (MotorControlInterface::*)(const geometry_msgs::Twist&amp;), MotorControlInterface*, const std::_Placeholder&lt;1&gt;&amp;&gt;::type*)'
         );
         ^
  In file included from /home/ubuntu/Arduino/libraries/ros_lib/ros/node_handle.h:60:0,
                   from /home/ubuntu/Arduino/libraries/ros_lib/ros.h:38,
                   from /home/ubuntu/Arduino/*****/*****.ino:28:
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:107:3: note: candidate: ros::Subscriber&lt;MsgT, void&gt;::Subscriber(const char*, ros::Subscriber&lt;MsgT, void&gt;::CallbackT, int) [with MsgT = geometry_msgs::Twist; ros::Subscriber&lt;MsgT, void&gt;::CallbackT = void (*)(const geometry_msgs::Twist&amp;)]
     Subscriber(const char * topic_name, CallbackT cb, int endpoint = rosserial_msgs::TopicInfo::ID_SUBSCRIBER) :
     ^
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:107:3: note:   no known conversion for argument 2 from 'std::_Bind_helper&lt;false, void (MotorControlInterface::*)(const geometry_msgs::Twist&amp;), MotorControlInterface*, const std::_Placeholder&lt;1&gt;&amp;&gt;::type* {aka std::_Bind&lt;std::_Mem_fn&lt;void (MotorControlInterface::*)(const geometry_msgs::Twist&amp;)&gt;(MotorControlInterface*, std::_Placeholder&lt;1&gt;)&gt;*}' to 'ros::Subscriber&lt;geometry_msgs::Twist&gt;::CallbackT {aka void (*)(const geometry_msgs::Twist&amp;)}'
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate: constexpr ros::Subscriber&lt;geometry_msgs::Twist&gt;::Subscriber(const ros::Subscriber&lt;geometry_msgs::Twist&gt;&amp;)
   class Subscriber&lt;MsgT, void&gt;: public Subscriber_
         ^
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note:   candidate expects 1 argument, 2 provided
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note: candidate: constexpr ros::Subscriber&lt;geometry_msgs::Twist&gt;::Subscriber(ros::Subscriber&lt;geometry_msgs::Twist&gt;&amp;&amp;)
  /home/ubuntu/Arduino/libraries/ros_lib/ros/subscriber.h:101:7: note:   candidate expects 1 argument, 2 provided
  
  exit status 1
  taking address of temporary [-fpermissive]
  
  </code></pre>
  <p>It seems to me like <code>std::bind</code> of the callback function does not return what I expect it to, therefore the reference fails. According to <a href="https://en.cppreference.com/w/cpp/utility/functional/bind" rel="nofollow noreferrer">this</a> though, the return value is a function object.</p>
  <p>As this is my first C/C++ project in a while, I am thankful for any advice on how to get this working. I have spent quite a few hours on this and am not really sure how to continue as the error message doesn't really help me.</p>
  <p><strong>SOLUTION:</strong>
  <a href="https://answers.ros.org/question/258249/publisher-or-subscriber-inside-a-class-rosserial/" rel="nofollow noreferrer">This solution</a> works:</p>
  <pre><code>#include &lt;ros.h&gt;
  #include &lt;geometry_msgs/Twist.h&gt;
  
  ros::NodeHandle nh;
  
  const char cmd_vel_topic[] = &quot;/cmd_vel&quot;
  
  class MotorControlInterface {
  
    public:
      MotorControlInterface() 
      : twistSubscriber(cmd_vel_topic, &amp;MotorControlInterface::twistCallback, this)
      {
        ; // Stuff to do in the constructor
      };
  
      // FreeRTOS task to call from main
      void TaskMotorControl(void *pvParameters)
      {    
        nh.subscribe(twist_sub);
  
        for(;;)
        {
          // Do some stuff with velocity commands
          handleMotorSpeeds();
          vTaskDelay( 10 );
        }
      };
  
    private:
      // Instance variable I want to store message data in
      double vel_cmd_x;
      ros::Subscriber&lt;geometry_msgs::Twist, MotorControlInterface&gt; twistSubscriber;
  
      // Callback function 
      void twistCallback(const geometry_msgs::Twist&amp; twist_msg)
      {
        // Save velocity command
        vel_cmd_x = twist_msg.linear.x;
      };
  
  };
  </code></pre>