Search code examples
c++classboostcallbackshared-ptr

Passing a variable between callback and main


I'm using ROS with C++ and after receiving data from a topic in void callback(), I need to pass this data to a variable in int main(). What I've found out so far is that I can do it using a boost shared pointer and should use a "class in the program with callback as member function". Part of my code so far:

double pos_z;
void callback(gazebo_msgs::LinkStates msgs_ls)
{
   double pos_z = msgs_ls.pose[43].position.z
   pos_z = pos_z + 1;
}
int main(int argc, char **argv)
{
   ros::init(...);
   ros::Nodehandle n;
   ros::Subscriber ls_sub = n.subscribe("/gazebo/link_states", 10, callback);
   ros::ServiceClient sls_client = n.serviceClient<gazebo_msgs::SetLinkState>("/gazebo/set_link_state");
   gazebo_msgs::SetLinkState setLinkState;
   while (ros::ok))
   {
      setLinkState.request.link_state.position.z = pos_z;
      sls_client.call(setLinkState);
  }

About the shared pointer: this could be boost::shared_ptr<double> a_ptr(&a, noop_delete with auto noop_delete = [](double *){} but I don't really understand how to implement this. Also the mentioned class with callback as member function is unclear to me. Examples show implementations using C, and I don't know if I can use that. Thank you for any help.


Solution

  • The advice you were given is good :

    use a "class in the program with callback as member function"

    You do it like that :

    class SuperCoolRobot {
    public:
      SuperCoolRobot ():pos_z(0) {
        // Note : we provide the callback (a member) + a state (this)
        ls_sub = n.subscribe("/gazebo/link_states", 10, SuperCoolRobot::link_state_callback, this);
      }
    
      void link_state_callback(gazebo_msgs::LinkStates msgs_ls) {
        pos_z = msgs_ls.pose[43].position.z + 1;
      }
    
      void run() {
        gazebo_msgs::SetLinkState setLinkState;
        while (ros::ok))
        {
          setLinkState.request.link_state.position.z = pos_z;
          sls_client.call(setLinkState);
        }
      }
    protected:
      // state here
      ros::Nodehandle n;
      ros::Subscriber ls_sub;
      double pos_z;
    };
    

    Then the main :

    int main(int argc, char **argv) {
      SuperCoolRobot robot;
      robot.run();
    }
    

    Note that I don't know ROS so I just threw what I understood from your code. Ajust it of course.