0
$\begingroup$

Rosanswers logo

Followed the tutorial, adapted it to my project. When I call the advertiseService in the main, it works. When it is called in a function called by main, it doesn't.

Here some code. First, tutorial example which works :

#include "ros/ros.h"
#include "testService/AddTwoInts.h"

bool add(testService::AddTwoInts::Request  &req, testService::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_server");
  ros::NodeHandle n;

  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

In my use case, I need to set up a service in a separate file. I"m surprised this doesn't work

#include "ros/ros.h"
#include "testService/AddTwoInts.h"

void testFunction(ros::NodeHandle &n);

bool add(testService::AddTwoInts::Request  &req,
         testService::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_server");
  ros::NodeHandle n;

  testFunction(n);

  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

void testFunction(ros::NodeHandle &n)
{
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);  
}

The service doesn't show up when typing rosservice list.

First, I made a new node handle in my function. Then, I tried to pass the main's node Handle by value, reference, pointer, global variable to my function. No changes. I thought about creating a function returning an object with topic name and function pointer inside it, but function pointer callback are callback-specific and my main can't know their type. Any one got a lead to how to do this?


Originally posted by Vic on ROS Answers with karma: 71 on 2021-01-19

Post score: 0


Original comments

Comment by Delb on 2021-01-19:
Can you edit your question to show us your code ?

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

The problem is because you declare and define the service within the function testFunction, so once the function is finished the service goes out of scope and doesn't exist anymore.

If you sleep some time in your function you will see that the service exists while you are still in the function :

void testFunction(ros::NodeHandle &n)
{
  ros::ServiceServer service = n.advertiseService("add_two_ints", add);
  ros::Rate r(0.2); //Sleep for 5 seconds
  r.sleep();  
}

About your issue :

In my use case, I need to set up a service in a separate file.

I'm not sure to get why setting up a service in a separate file requires you to use a function like in your example. Maybe you could add more details about this. I would recommend creating a class in your separate file that would have ros::ServiceServer as member so that when you create an instance of this class in your main the service is kept alive.


Originally posted by Delb with karma: 3907 on 2021-01-19

This answer was ACCEPTED on the original site

Post score: 2


Original comments

Comment by Vic on 2021-01-19:
Thanks for the quick feedback.

For the posterity : this works

#include "ros/ros.h"
#include "testService/AddTwoInts.h"

class testClass
{
public: 
  ros::ServiceServer service;
};

testClass testScope;

void testFunction(ros::NodeHandle &n);

bool add(testService::AddTwoInts::Request  &req,
         testService::AddTwoInts::Response &res)
{
  res.sum = req.a + req.b;
  ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b);
  ROS_INFO("sending back response: [%ld]", (long int)res.sum);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "add_two_ints_server");
  ros::NodeHandle n;

  testFunction(n);

  ROS_INFO("Ready to add two ints.");
  ros::spin();

  return 0;
}

void testFunction(ros::NodeHandle &n)
{
  testScope.service = n.advertiseService("add_two_ints", add);  
}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.