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

Ros service not advertised in functions

asked 2021-01-19 04:09:41 -0600

Vic gravatar image

updated 2021-01-19 09:41:33 -0600

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?

edit retag flag offensive close merge delete

Comments

1

Can you edit your question to show us your code ?

Delb gravatar image Delb  ( 2021-01-19 07:21:45 -0600 )edit

1 Answer

Sort by ยป oldest newest most voted
2

answered 2021-01-19 09:18:11 -0600

Delb gravatar image

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.

edit flag offensive delete link more

Comments

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);  
}
Vic gravatar image Vic  ( 2021-01-19 09:41:15 -0600 )edit

Question Tools

Stats

Asked: 2021-01-19 04:09:41 -0600

Seen: 685 times

Last updated: Jan 19 '21