ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

#include<thread>
void spin_wrapper()
{
  ros::spin();
}
...
int main(int argc, char *argv[])
{
  ...
  //create and start a thread
  std::thread spin_thread(spin_wrapper);
  //send request
  if(client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Note that thread works since C++11 so your CMakeLists.txt file should add add_compile_options(-std=c++11) to enable the function.

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

#include<thread>
void spin_wrapper()
{
  ros::spin();
}
...
int main(int argc, char *argv[])
{
  ...
  //create and start a thread
  std::thread spin_thread(spin_wrapper);
  //send request
  if(client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Note that thread works since C++11 so your CMakeLists.txt file should add add_compile_options(-std=c++11) to enable the function.

Update Thank @”gvdhoorn“ for better solutions of multi-threaded spinners. I update the solution using ros::AsyncSpinner. int main(int argc, char *argv[]) { ... //create and start a thread ros::AsyncSpinner spinner(1); // Use 1 thread spinner.start(); //send request if(client.call(srv)) { ROS_INFO("Sum: %ld", (long int)srv.response.sum);

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

#include<thread>
void spin_wrapper()
{
  ros::spin();
}
...
int main(int argc, char *argv[])
{
  ...
  //create and start a thread
  std::thread spin_thread(spin_wrapper);
  //send request
  if(client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Note that thread works since C++11 so your CMakeLists.txt file should add add_compile_options(-std=c++11) to enable the function.

Update Thank @”gvdhoorn“ @gvdhoorn for better solutions of multi-threaded spinners. I update the solution using ros::AsyncSpinner. int main(int argc, char *argv[]) { ... //create and start a thread ros::AsyncSpinner spinner(1); // Use 1 thread spinner.start(); //send request if(client.call(srv)) { ROS_INFO("Sum: %ld", (long int)srv.response.sum);

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

#include<thread>
void spin_wrapper()
{
  ros::spin();
}
...
int main(int argc, char *argv[])
{
  ...
  //create and start a thread
  std::thread spin_thread(spin_wrapper);
  //send request
  if(client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Note that thread works since C++11 so your CMakeLists.txt file should add add_compile_options(-std=c++11) to enable the function.

Update Update

Thank @gvdhoorn for better solutions of multi-threaded spinners. I update the solution using ros::AsyncSpinner. int main(int argc, char *argv[]) { ... //create and start a thread ros::AsyncSpinner spinner(1); // Use 1 thread spinner.start(); //send request if(client.call(srv)) { ROS_INFO("Sum: %ld", (long int)srv.response.sum);

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Based on your code, the request to service is processed at ros::spinOnce(), and client.call() is waiting the response from service. Then a deadlock happens and your program gets stuck at client.call() as you found.

Using two different nodes, or two processes, is the best way to implement this example because the purpose of ServiceServer is to provide service to any clients. If you still require to implement this example in a node, I would suggest you create a thread to handle either ros::spinOnce() or client.call.

#include<thread>
void spin_wrapper()
{
  ros::spin();
}
...
int main(int argc, char *argv[])
{
  ...
  //create and start a thread
  std::thread spin_thread(spin_wrapper);
  //send request
  if(client.call(srv))
  {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

  }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}

Note that thread works since C++11 so your CMakeLists.txt file should add add_compile_options(-std=c++11) to enable the function.

Update

Thank @gvdhoorn for better solutions of multi-threaded spinners. I update the solution using ros::AsyncSpinner. .

int main(int argc, char *argv[])
    {
    {
  ...
   //create and start a thread
   ros::AsyncSpinner spinner(1); // Use 1 thread
   spinner.start();
   //send request
   if(client.call(srv))
      {
    {
    ROS_INFO("Sum: %ld", (long int)srv.response.sum);   

   }
  else
  {
    ROS_ERROR("Failed to call service add_two_ints");
    return 1;
  }
  //ros::spinOnce();
}