How do I correctly use the service server and subscriber? C++

Hi

I understand that I need to create a Service Server with OOP, create the callbacks to service_server and subscriber. But when I tried to use my variables on other different side than subscriber_callback these is not update. So, they just update once time and then mantain the value. Why?? I think that I’m use classes correctly

min_left_laser, min_right_laser and min_front_laser are protected variables in the class.

#include <boost/mpl/bool_fwd.hpp>
#include <find_wall_cpp/find_wall.hpp>
#include <iterator>
#include <vector>

// Constructor
ServerClass::ServerClass(ros::NodeHandle nh) {
  // Start Service
  my_service =
      nh.advertiseService("/find_wall", &ServerClass::serviceCallback, this);
  ROS_INFO("The Service /find_wall is READY");
  // Start Subscriber
  sub_ = nh.subscribe("/scan", 1000, &ServerClass::sensorCallback, this);
  // Start Publisher
  pub_ = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1);

  // Create flags
  flags.insert(std::pair<std::string, int>("front_wall", false));
  flags.insert(std::pair<std::string, int>("close_wall", false));
  flags.insert(std::pair<std::string, int>("parallel_wall", false));
}

// Turtlebot3 movement

// Stop
void ServerClass::stop() {
  velocity.linear.x = 0.0;
  velocity.angular.z = 0.0;
}

void ServerClass::turn_left() {
  velocity.linear.x = 0.0;
  velocity.angular.z = 0.2;
}

void ServerClass::turn_right() {
  velocity.linear.x = 0.0;
  velocity.angular.z = -0.2;
}

void ServerClass::forward() {
  velocity.linear.x = 0.05;
  velocity.angular.z = 0.0;
}

void ServerClass::backward() {
  velocity.linear.x = -0.02;
  velocity.angular.z = 0.0;
}

void ServerClass::slow_turn() {
  velocity.linear.x = 0.0;
  velocity.angular.z = 0.09;
}
void ServerClass::publish() { pub_.publish(velocity); }

// Sensor_callback
void ServerClass::sensorCallback(const sensor_msgs::LaserScan::ConstPtr &msg) {

  std::vector<float> laserScan;
  laserScan = msg->ranges;

  std::vector<float> front_laser;
  std::copy(laserScan.begin() + 350, laserScan.begin() + 371,
            std::back_inserter(front_laser));

  std::copy(msg->ranges.begin() + 350, msg->ranges.begin() + 371,
            std::back_inserter(front_laser));
  min_front_laser = *min_element(front_laser.begin(), front_laser.end());

  std::vector<float> right_laser;
  std::copy(msg->ranges.begin() + 170, msg->ranges.begin() + 200,
            std::back_inserter(right_laser));
  min_right_laser = *min_element(right_laser.begin(), right_laser.end());

  std::vector<float> left_laser;
  std::copy(msg->ranges.begin() + 530, msg->ranges.begin() + 551,
            std::back_inserter(left_laser));
  min_left_laser = *min_element(left_laser.begin(), left_laser.end());

  // It is updated successfully here
  //   std::cout << "   min_l: " << min_left_laser << "   min_f: " <<
  //   min_front_laser
  //             << "   min_r: " << min_right_laser << std::endl;
}

// Service_callback
bool ServerClass::serviceCallback(find_wall_cpp::FindWall::Request &req,
                                  find_wall_cpp::FindWall::Response &res) {

  ROS_INFO("Callback called!");
  // Stop the robot
  stop();

  // Initialize the flags
  auto front = flags.find("front_wall");
  auto close = flags.find("close_wall");
  auto parallel = flags.find("parallel_wall");
  bool front_bool = false;
  int i = 0;
  while (!(front->second)) {

    if (i == 0) {

      if (min_right_laser > min_left_laser) {
        ROS_INFO("Left!!");
        turn_left();

      } else if (min_left_laser > min_right_laser) {

        ROS_INFO("Right!!");
        turn_right();
      }
      i += 1;
    }

      // It isn't updated successfully here, mantain the first value
      //   std::cout << "   min_l: " << min_left_laser << "   min_f: " <<
      //   min_front_laser
      //             << "   min_r: " << min_right_laser << std::endl;
      // So, the condition is never met and stuck here

    if (min_right_laser > min_front_laser && min_left_laser > min_front_laser) {
      ROS_INFO("Im on the while");
      front->second = true;
      break;
    }
    publish();
    ros::Duration(0.1).sleep();
  }
  ROS_INFO("Stop_1");
  stop();

  while (close->second == false) {
    ROS_INFO("Close");

    if (min_front_laser > 0.3) {
      forward();
    } else {
      backward();
      ros::Duration(0.1).sleep();
      close->second = true;
      break;
    }
    ros::Duration(0.1).sleep();
  }

  stop();

  while (parallel->second == false) {
    ROS_INFO("Turn");
    slow_turn();
    if (min_front_laser > min_right_laser && min_left_laser > 0.3) {
      stop();
      parallel->second = true;
    }
    ros::Duration(0.1).sleep();
  }
  if (front->second && close->second && parallel->second) {
    ROS_INFO("Complete!");
  }
  res.wallfound = true;
  ROS_INFO("FindWall service has been complete!");

  return true;
}

Hi @Voltedge ,

I saw your code and figured out something weird.

  1. Where is your class?
    I do not see a #include for your class header file in your code. So where is class ServerClass{...}; defined in your code?
  2. Also where is your main() function defined?
  3. Did you compile your code before execution?
    I would be surprised if you say that this code compiled without errors or warnings.

There must be something like:

class ServerClass{
private:
// ...

protected:
// ...

public:
// ...
};

int main(int argc, char **argv) {
// ...
return 0;
}

I think you need to fix your code to include a class. Rework on your code.

Regards,
Girish

Hi @girishkumar.kannan

Oh nono, that’s the .cpp, sorry to not put the header, here is.

  • Yes, I compile the entire package and there’s no error

    #include "ros/publisher.h"
    #include <find_wall_cpp/FindWall.h>
    #include <geometry_msgs/Twist.h>
    #include <ros/ros.h>
    #include <sensor_msgs/LaserScan.h>
    #include <vector>
    
    class ServerClass {
    
    private:
      // ROS Service Server
      ros::ServiceServer my_service;
    
      // ROS Subscribers
      ros::Subscriber sub_;
    
      // ROS Publishers
      ros::Publisher pub_;
    
      // min_lasers
      float min_right_laser;
      float min_left_laser;
      float min_front_laser;
    
      geometry_msgs::Twist velocity;
    
      // Laser_scan
      std::vector<float> laserScan;
      // Flags
      std::map<std::string, bool> flags;
    
    public:
      ServerClass(ros::NodeHandle nh);
      void sensorCallback(const sensor_msgs::LaserScan::ConstPtr &msg);
      bool serviceCallback(find_wall_cpp::FindWall::Request &req,
                           find_wall_cpp::FindWall::Response &res);
      void stop();
      void forward();
      void turn_left();
      void turn_right();
      void backward();
      void slow_turn();
      void publish();
    };
    

And that’s the main.cpp
Yes, I divide the package on 3 files

  #include <find_wall_cpp/find_wall.hpp>
  #include <ros/ros.h>
  #include <std_msgs/Int64.h>
  #include <std_srvs/SetBool.h>
  
  int main (int argc, char **argv)
  {
      ros::init(argc, argv, "find_wall_node");
      ros::NodeHandle nh;
      ServerClass srv = ServerClass(nh);
      ros::spin();
  }

Hi @Voltedge ,

Thanks for posting the other two files, now I can make a little bit more sense of your code.

These seem to be private and not protected. In case you did not notice them.

I am still having a little trouble understanding your problem. Could you post your terminal output (as a code-block) and explain what result you expect and what is your current result?
What should your robot do and what it is currently doing instead?
That way, I could help you better.

Regards,
Girish

Hi @girishkumar.kannan

Sure, I’ve got 3 flags,

  • “front_wall” which makes the robot turn towards the nearest wall
  • “close_wall” which makes the robot forward until 0.3 meters of the front wall
  • “parallel_wall” which makes the robot turns util it has the wall on the right side
    There are bool.

Expected Behavior:

The expected behavior must be, for example in while (!(front->second)).
first, the robot select one side to turn (right or left), just once time.
Then, the robot keep turning on this side until

     min_right_laser > min_front_laser && min_left_laser > min_front_laser

Then, I put the front->second = true and break the loop. Otherwise, it stays on loop.

Problem:

My sensorCallback dont actualize. So, he just read the first value, select the side of rotation and since the reading of the laser sensor is not updated, it gets stuck in the condition (!(front->second)). So, my problem it’s the sensorCallback don’t actualize.

Actually, when I compile, the sensorCallback works but when I send the client the laser_callback stops.

while (!(front->second)) {
    if (i == 0) {

      if (min_right_laser > min_left_laser) {
        ROS_INFO("Left!!");
        turn_left();

      } else if (min_left_laser > min_right_laser) {

        ROS_INFO("Right!!");
        turn_right();
      }
      i += 1;
    }

      // It isn't updated successfully here, mantain the first value
      //   std::cout << "   min_l: " << min_left_laser << "   min_f: " <<
      //   min_front_laser
      //             << "   min_r: " << min_right_laser << std::endl;
      // So, the condition is never met and stuck here

    if (min_right_laser > min_front_laser && min_left_laser > min_front_laser) {
      ROS_INFO("Im on the while");
      front->second = true;
      break;
    }
    publish();
    ros::Duration(0.1).sleep();
  }

Hi @Voltedge ,

Ok, I understand your issue now.

I think your subscriber declaration is the culprit.

You do not need 1000 messages in the queue. Keep it to 1 or 10. Not more than that.
The queue size is probably choking / blocking your code in the subscriber callback. I am guessing.

Other than the above,

  1. Have you tried running your service callback as a main function just to check if service function works fine? Without making a call from the client?
  2. You say that laser callback stops when you call the service from the client - does the client program also have a subscription to laser scan? Probably you have two subscribers from two different nodes, subscribing to the same laser scan topic.

The best way to check why your service hangs / stops right after you make a call from the client, is to print out as much debug statements as possible after each stage of code to see if the conditions are satisfied.

Another way would be to minimize your code to bare minimum functionality for a service server-client communication and then check if the service call works correctly.

Regards,
Girish

Hi @girishkumar.kannan

About the client, I just used the command:

  rosservice call /find_wall "{}"

I tried everything you mentioned, the server response with a minimal, change the sensor_callback queu_size but nothing seems to work.

There’s something I don’t understand, I change the service_callback to proof, let me show you.

  // Constructor
  ServerClass::ServerClass(ros::NodeHandle nh) {
    // Start Service
    my_service =
        nh.advertiseService("/find_wall", &ServerClass::serviceCallback, this);
    ROS_INFO("The Service /find_wall is READY");
    // Start Subscriber
    //   sub_ = nh.subscribe("/scan", 10, &ServerClass::sensorCallback, this);
    pub_ = nh.advertise<geometry_msgs::Twist>("/cmd_vel", 1);
  
    // Start flags on false
    flags.insert(std::pair<std::string, int>("front_wall", false));
    flags.insert(std::pair<std::string, int>("close_wall", false));
    flags.insert(std::pair<std::string, int>("parallel_wall", false));
  
    rate_hz_ = 1;
  
    rate_ = new ros::Rate(rate_hz_);
  }
  // Service_callback
  bool ServerClass::serviceCallback(find_wall_cpp::FindWall::Request &req,
                                    find_wall_cpp::FindWall::Response &res) {
  
    ROS_INFO("Callback called!");
    
    sub_ = nh.subscribe("/scan", 10, &ServerClass::sensorCallback, this);
  
    for (int i = 0; i < 10; i++) {
      std::cout << "   min_l: " << min_left_laser
                << "   min_f: " << min_front_laser
                << "   min_r: " << min_right_laser << std::endl;
      rate_->sleep();
    }
  
    res.wallfound = true;
    ROS_INFO("FindWall service has been complete!");
  
    return true;
  }

Shell Response

user:~/catkin_ws$ rosrun find_wall_cpp wall[ INFO] [1672947549.347973177]: The Service /find_wall is READY
[ INFO] [1672947553.565024899, 1138.910000000]: Callback called!
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
   min_l: 4.55828e-41   min_f: 1.4013e-45   min_r: -2.28684e-19
[ INFO] [1672947568.186004789, 1147.938000000]: FindWall service has been complete!

Hi @girishkumar.kannan

That’s what I said when the sensor_callback stops when I called the service server

  • sub_min_f/r/l it’s printing by the sensor_callback

  • min_f/rl it’s printing by the service_callback

    user:~/catkin_ws$ rosrun find_wall_cpp wall[ INFO] [1672948959.172976910]: The Service /find_wall is READY
       sub_min_l: 0.382239   sub_min_f: 0.698257   sub_min_r: 0.736231
       sub_min_l: 0.38432   sub_min_f: 0.730318   sub_min_r: 0.723194
       sub_min_l: 0.389481   sub_min_f: 0.748224   sub_min_r: 0.713188
       sub_min_l: 0.36109   sub_min_f: 0.777778   sub_min_r: 0.687329
       sub_min_l: 0.344151   sub_min_f: 0.796972   sub_min_r: 0.664893
       sub_min_l: 0.317604   sub_min_f: 0.826383   sub_min_r: 0.64401
       sub_min_l: 0.286511   sub_min_f: 0.875783   sub_min_r: 0.643053
       sub_min_l: 0.299402   sub_min_f: 0.905273   sub_min_r: 0.629194
       sub_min_l: 0.296771   sub_min_f: 0.960995   sub_min_r: 0.603438
       sub_min_l: 0.298516   sub_min_f: 1.00194   sub_min_r: 0.604674
       sub_min_l: 0.294739   sub_min_f: 1.06848   sub_min_r: 0.586974
       sub_min_l: 0.32347   sub_min_f: 1.12311   sub_min_r: 0.583207
       sub_min_l: 0.336084   sub_min_f: 1.11499   sub_min_r: 0.566834
       sub_min_l: 0.374814   sub_min_f: 1.10827   sub_min_r: 0.569486
       sub_min_l: 0.439488   sub_min_f: 1.10691   sub_min_r: 0.558549
       sub_min_l: 0.437215   sub_min_f: 1.08791   sub_min_r: 0.548264
       sub_min_l: 0.514438   sub_min_f: 1.08124   sub_min_r: 0.555252
       sub_min_l: 1.25091   sub_min_f: 1.06976   sub_min_r: 0.544218
       sub_min_l: 1.24281   sub_min_f: 1.0727   sub_min_r: 0.549831
       sub_min_l: 1.23493   sub_min_f: 1.06237   sub_min_r: 0.543943
       sub_min_l: 1.23855   sub_min_f: 1.06644   sub_min_r: 0.541946
       sub_min_l: 1.24446   sub_min_f: 1.05902   sub_min_r: 0.529822
       sub_min_l: 1.24593   sub_min_f: 1.06655   sub_min_r: 0.548268
    [ INFO] [1672948966.945460457, 2017.212000000]: Callback called!
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
       min_l: 1.24593   min_f: 1.06655   min_r: 0.548268
    [ INFO] [1672948981.641868719, 2026.212000000]: FindWall service has been complete!
       sub_min_l: 0.982599   sub_min_f: 1.29364   sub_min_r: 1.04695
       sub_min_l: 0.978382   sub_min_f: 1.29001   sub_min_r: 1.0518
       sub_min_l: 0.988621   sub_min_f: 1.26787   sub_min_r: 1.05297
    

The sensor_callback keeps printing and actualize again when service_callback has finished

Hi @Voltedge ,

Now I see what your problem is.
“Service Callback blocks Subscriber (or other) Callback(s) in the Program”
The above is the problem that you will search on Google.

Firstly, I have never faced this issue when I worked with ROS(1). [I have completed the course presentation by the way.]

Now let me give you my suggestions, based on my experience so far:

  1. You have something in your service callback code that is blocking your subscriber callback. Maybe it is the loop(s) - try adding a rospy.sleep(1.0) before the end of (each) loop to see if the subscriber data is getting printed in the 1 sec delay during the service callback.
  2. Try to do less computation in the subscriber callback. Probably that is getting stuck. Maybe the time required to complete one set of subscriber callback is more than the time required to complete the service callback. Move all the computation code which is inside the subscriber callback to outside of the subscriber callback.
  3. As a last resort, you can try implementing Spinner in ROS1.
    Refer this article on how to use it: Concurrency and parallelism in ROS 1 and ROS 2: application APIs
    This article explains the use of Spinner and Executor used in ROS1 and ROS2, respectively. Just follow the section for ROS1.

This could either be a programming issue or a configuration issue. Programming issues can be solved quicker (with re-programming of course). If it is a configuration issue, then The Construct team could help you with some updates in your course environment.

Regards,
Girish

1 Like

Hi @girishkumar.kannan

Thanks for your advices!

Now I can run my service server and action without problems.

After a long time of searching I found how create a action_client with OOP and this made me doubt.

I try to create a action_client and a publisher<cmd_vel> subscriber to advance and follow the wall meanwhile the action_server sends the feedback (current_distance)

  #include <mantain_distance_cpp/robot.hpp>
  #include <ros/ros.h>
  #include <actionlib/client/simple_action_client.h>
  
  using namespace actionlib_tutorials;
  
  typedef actionlib::SimpleActionClient<odom_record_cpp::OdomRecordAction> Client;
  
  class ActionClient
  {
  public:
    ActionClient() : ac("client_record", true)
    {
      ROS_INFO("Waiting for action server to start.");
      ac.waitForServer();
      ROS_INFO("Action server started, sending goal.");
    }
  
    void ac_start()
    {
      odom_record_cpp::OdomRecordGoal goal;
  
      // Need boost::bind to pass in the 'this' pointer
      ac.sendGoal(goal,
                  boost::bind(&ActionClient::doneCb, this, _1, _2),
                  Client::SimpleActiveCallback(),
                  Client::SimpleFeedbackCallback());
  
    }
  
  void doneCb(
      const actionlib::SimpleClientGoalState &state,
      const odom_record_cpp::OdomRecordResultConstPtr &result) {
  
    ROS_INFO("[State Result]: %s", state.toString().c_str());
    ROS_INFO("The Action has been completed");
    // ros::shutdown();
  
  }
  
  private:
    Client ac;
  };
  
  int main (int argc, char **argv)
  {
    ros::init(argc, argv, "Test_OdomRecord_Client");
    ActionClient my_node;
    my_node.ac_start();
    ros::spin();
    return 0;
  }

Example: actionlib_tutorials/Tutorials/Writing a Callback Based Simple Action Client - ROS Wiki

I’m trying to compile and returns an error that I don’t understand

  user:~/catkin_ws$ catkin_make --only-pkg-with-deps mantain_distance_cpp
  Base path: /home/user/catkin_ws
  Source space: /home/user/catkin_ws/src
  Build space: /home/user/catkin_ws/build
  Devel space: /home/user/catkin_ws/devel
  Install space: /home/user/catkin_ws/install
  Whitelisted packages: find_wall_cpp, mantain_distance_cpp
  ####
  #### Running command: "make cmake_check_build_system" in "/home/user/catkin_ws/build"
  ####
  ####
  #### Running command: "make -j8 -l8" in "/home/user/catkin_ws/build"
  ####
  [  0%] Built target _find_wall_cpp_generate_messages_check_deps_FindWall
  [  0%] Built target rosgraph_msgs_generate_messages_py[  0%] Built target rosgraph_msgs_generate_messages_eus
  [  0%] Built target roscpp_generate_messages_lisp
  [  0%] Built target roscpp_generate_messages_nodejs
  [  0%] Built target roscpp_generate_messages_py
  [  0%] Built target rosgraph_msgs_generate_messages_nodejs[  0%] Built target rosgraph_msgs_generate_messages_lisp
  [  0%] Built target roscpp_generate_messages_eus
  [  0%] Built target roscpp_generate_messages_cpp
  [  0%] Built target sensor_msgs_generate_messages_cpp
  [  0%] Built target geometry_msgs_generate_messages_lisp
  [  0%] Built target nav_msgs_generate_messages_lisp
  [  0%] Built target nav_msgs_generate_messages_cpp
  [  0%] Built target sensor_msgs_generate_messages_lisp
  [  0%] Built target sensor_msgs_generate_messages_nodejs
  [  0%] Built target odom_record_cpp_generate_messages_nodejs
  [  0%] Built target nav_msgs_generate_messages_eus
  [  0%] Built target actionlib_msgs_generate_messages_lisp
  [  0%] Built target odom_record_cpp_generate_messages_lisp
  [  0%] Built target geometry_msgs_generate_messages_eus
  [  0%] Built target odom_record_cpp_generate_messages_py
  [  0%] Built target odom_record_cpp_generate_messages_eus
  [  0%] Built target geometry_msgs_generate_messages_cpp
  [  0%] Built target geometry_msgs_generate_messages_nodejs
  [  0%] Built target nav_msgs_generate_messages_nodejs
  [  0%] Built target actionlib_msgs_generate_messages_eus
  [  0%] Built target sensor_msgs_generate_messages_py
  [  0%] Built target geometry_msgs_generate_messages_py
  [  0%] Built target nav_msgs_generate_messages_py
  [  0%] Built target odom_record_cpp_generate_messages_cpp
  [  0%] Built target actionlib_msgs_generate_messages_py
  [  0%] Built target actionlib_generate_messages_cpp
  [  0%] Built target actionlib_msgs_generate_messages_cpp
  [  0%] Built target actionlib_generate_messages_eus
  [  0%] Built target actionlib_generate_messages_lisp
  [  0%] Built target sensor_msgs_generate_messages_eus
  [  0%] Built target actionlib_generate_messages_nodejs
  [  0%] Built target actionlib_msgs_generate_messages_nodejs
  [  0%] Built target actionlib_generate_messages_py
  [  7%] Building CXX object mantain_distance_cpp/CMakeFiles/mantain_distance_cpp.dir/src/robot.cpp.o
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:15,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:48,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp: In instantiation of 'void boost::function0<R>::assign_to(Functor) [with Functor = void (RobotClass::*)(); R = void]':
  /usr/include/boost/function/function_template.hpp:720:7:   required from 'boost::function0<R>::function0(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(); R = void; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /usr/include/boost/function/function_template.hpp:1068:16:   required from 'boost::function<R()>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(); R = void; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:72:42:   required from here
  /usr/include/boost/function/function_template.hpp:921:9: error: no class template named 'apply' in 'struct boost::detail::function::get_invoker0<boost::detail::function::member_ptr_tag>'
    921 |         handler_type;
        |         ^~~~~~~~~~~~
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:29,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:58,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp: In instantiation of 'static void boost::detail::function::function_void_mem_invoker2<MemberPtr, R, T0, T1>::invoke(boost::detail::function::function_buffer&, T0, T1) [with MemberPtr = void (RobotClass::*)(const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&); R = void; T0 = const actionlib::SimpleClientGoalState&; T1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]':
  /usr/include/boost/function/function_template.hpp:931:38:   required from 'void boost::function2<R, T1, T2>::assign_to(Functor) [with Functor = void (RobotClass::*)(const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&); R = void; T0 = const actionlib::SimpleClientGoalState&; T1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]'
  /usr/include/boost/function/function_template.hpp:720:7:   required from 'boost::function2<R, T1, T2>::function2(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&); R = void; T0 = const actionlib::SimpleClientGoalState&; T1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /usr/include/boost/function/function_template.hpp:1068:16:   required from 'boost::function<R(T0, T1)>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&); R = void; T0 = const actionlib::SimpleClientGoalState&; T1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:72:42:   required from here
  /usr/include/boost/function/function_template.hpp:230:11: error: no match for call to '(boost::_mfi::mf2<void, RobotClass, const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&>) (const actionlib::SimpleClientGoalState&, const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&)'
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:278:7: note: candidate: 'R boost::_mfi::mf2<R, T, A1, A2>::operator()(T*, A1, A2) const [with R = void; T = RobotClass; A1 = const actionlib::SimpleClientGoalState&; A2 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]'
    278 |     R operator()(T * p, A1 a1, A2 a2) const
        |       ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:278:7: note:   candidate expects 3 arguments, 2 provided
  /usr/include/boost/bind/mem_fn_template.hpp:283:25: note: candidate: 'template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(U&, A1, A2) const [with U = U; R = void; T = RobotClass; A1 = const actionlib::SimpleClientGoalState&; A2 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]'
    283 |     template<class U> R operator()(U & u, A1 a1, A2 a2) const
        |                         ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:283:25: note:   template argument deduction/substitution failed:
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:29,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:58,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp:230:11: note:   candidate expects 3 arguments, 2 provided
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:291:25: note: candidate: 'template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(const U&, A1, A2) const [with U = U; R = void; T = RobotClass; A1 = const actionlib::SimpleClientGoalState&; A2 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]'
    291 |     template<class U> R operator()(U const & u, A1 a1, A2 a2) const
        |                         ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:291:25: note:   template argument deduction/substitution failed:
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:29,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:58,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp:230:11: note:   candidate expects 3 arguments, 2 provided
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:299:7: note: candidate: 'R boost::_mfi::mf2<R, T, A1, A2>::operator()(T&, A1, A2) const [with R = void; T = RobotClass; A1 = const actionlib::SimpleClientGoalState&; A2 = const boost::shared_ptr<const odom_record_cpp::OdomRecordResult_<std::allocator<void> > >&]'
    299 |     R operator()(T & t, A1 a1, A2 a2) const
        |       ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:299:7: note:   candidate expects 3 arguments, 2 provided
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:22,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:53,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp: In instantiation of 'static void boost::detail::function::function_void_mem_invoker1<MemberPtr, R, T0>::invoke(boost::detail::function::function_buffer&, T0) [with MemberPtr = void (RobotClass::*)(const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]':
  /usr/include/boost/function/function_template.hpp:931:38:   required from 'void boost::function1<R, T1>::assign_to(Functor) [with Functor = void (RobotClass::*)(const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]'
  /usr/include/boost/function/function_template.hpp:720:7:   required from 'boost::function1<R, T1>::function1(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /usr/include/boost/function/function_template.hpp:1068:16:   required from 'boost::function<R(T0)>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = void (RobotClass::*)(const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&); R = void; T0 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
  /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:72:42:   required from here
  /usr/include/boost/function/function_template.hpp:230:11: error: no match for call to '(boost::_mfi::mf1<void, RobotClass, const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&>) (const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&)'
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:163:7: note: candidate: 'R boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R = void; T = RobotClass; A1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]'
    163 |     R operator()(T * p, A1 a1) const
        |       ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:163:7: note:   candidate expects 2 arguments, 1 provided
  /usr/include/boost/bind/mem_fn_template.hpp:168:25: note: candidate: 'template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(U&, A1) const [with U = U; R = void; T = RobotClass; A1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]'
    168 |     template<class U> R operator()(U & u, A1 a1) const
        |                         ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:168:25: note:   template argument deduction/substitution failed:
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:22,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:53,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp:230:11: note:   candidate expects 2 arguments, 1 provided
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:176:25: note: candidate: 'template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(const U&, A1) const [with U = U; R = void; T = RobotClass; A1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]'
    176 |     template<class U> R operator()(U const & u, A1 a1) const
        |                         ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:176:25: note:   template argument deduction/substitution failed:
  In file included from /usr/include/boost/function/detail/maybe_include.hpp:22,
                   from /usr/include/boost/function/detail/function_iterate.hpp:14,
                   from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:53,
                   from /usr/include/boost/function.hpp:71,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/function/function_template.hpp:230:11: note:   candidate expects 2 arguments, 1 provided
    230 |           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
        |           ^~~~~~~~~~~~~~~~~~~~~
  In file included from /usr/include/boost/bind/mem_fn.hpp:215,
                   from /usr/include/boost/mem_fn.hpp:22,
                   from /usr/include/boost/function/detail/prologue.hpp:18,
                   from /usr/include/boost/function.hpp:30,
                   from /opt/ros/noetic/include/ros/forwards.h:40,
                   from /opt/ros/noetic/include/ros/service_client.h:31,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/include/mantain_distance_cpp/robot.hpp:2,
                   from /home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:1:
  /usr/include/boost/bind/mem_fn_template.hpp:184:7: note: candidate: 'R boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R = void; T = RobotClass; A1 = const boost::shared_ptr<const odom_record_cpp::OdomRecordFeedback_<std::allocator<void> > >&]'
    184 |     R operator()(T & t, A1 a1) const
        |       ^~~~~~~~
  /usr/include/boost/bind/mem_fn_template.hpp:184:7: note:   candidate expects 2 arguments, 1 provided
  make[2]: *** [mantain_distance_cpp/CMakeFiles/mantain_distance_cpp.dir/build.make:63: mantain_distance_cpp/CMakeFiles/mantain_distance_cpp.dir/src/robot.cpp.o] Error 1
  make[1]: *** [CMakeFiles/Makefile2:1339: mantain_distance_cpp/CMakeFiles/mantain_distance_cpp.dir/all] Error 2
  make: *** [Makefile:141: all] Error 2
  Invoking "make -j8 -l8" failed

Where should I start to understand this error?

Hi @Voltedge ,

Firstly, I understand your keenness and practice to keep the c++ header files and program files separately. That is good! I am not saying no to that. BUT, please make one single .cpp file first. Get the program working first without splitting the code into multiple files. Once you are sure that your code works without any issues, then work on separating the code into headers, main and other parts.

Secondly, whenever you post a block of code, please add the file name of code on top.
Example:

This is my action_client.cpp:

#include <ros/ros.h>
// other includes

class Whatever{...};

int main (...){
// blah blah blah
return 0;
}

This way we can see all your codes under one single file and understand which part of code does what and where you have the bugs in your code.

When you get compilation errors, usually the very first error is where the bug is present in your code.

In your case, the first error is with handler_type in your error logs.

/home/user/catkin_ws/src/mantain_distance_cpp/src/robot.cpp:72:42:   required from here
/usr/include/boost/function/function_template.hpp:921:9: error: no class template named 'apply' in 'struct boost::detail::function::get_invoker0<boost::detail::function::member_ptr_tag>'
    921 |         handler_type;
        |         ^~~~~~~~~~~~

The line immediately above the error line indicates something in mantain_distance_cpp/src/robot.cpp.

Since you have not posted your robot.cpp, we will have no clue as to what to look for.

So do the following:

  1. Make one single file for action client.
  2. Check if the code works.
  3. If you still have this issue, then post that single .cpp file (with file name) along with the error output.

Regards,
Girish

PS: The correct spelling for maintain has two i’s. You seem to write mantain all over.

1 Like