Ask Your Question
3

Error with service server for Arduino

asked 2018-11-24 08:08:43 -0500

Mirzam gravatar image

Hi folks, I am trying to build a service server on an Arduino UNO using ROS. I am running ROS Kinetic on Ubuntu 16.04. I am currently stuck with the following problem and I do not know how to solve it. I would appreciate if you can help me out.

First of all, the script I built to test if the workspace works correctly is posted below:

#include <ros.h>
#include <helloworld_msgs/ModeSelect.h>
#include <Arduino.h>
#include <std_srvs/Empty.h>

// Create roscpp's interface for creating subscribers, publishers, etc
ros::NodeHandle n;

void setup()
{
  // Initialize node
  n.initNode();
}

void loop()
{
  n.spinOnce();
  delay(1000);
}

After building this package using 'catkin build', I obtained the following message indicating it was built successfully:

Warnings   << helloworld:make /home/mirzam/cmaketut_ws/logs/helloworld/build.make.165.log
make[3]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.
Firmware Size:  [Program: 8424 bytes (25.7%)]  [Data: 1277 bytes (62.4%)] on atmega328p
EEPROM   Size:  [Program: 0 bytes (0.0%)]  [Data: 0 bytes (0.0%)] on atmega328p

cd /home/mirzam/cmaketut_ws/build/helloworld; catkin build --get-env helloworld | catkin env -si  /usr/bin/make --jobserver-fds=6,7 -j; cd -

Therefore, I assume that the functions for creating a service server are available now for use. The scripts for the CMake list and package.xml for the helloworld package (the package that contains the servernode.cpp) can be found in the following two links respectively: link text and link text

The CMake file inside the directory where the script is located can be found here: link text

Programming the code onto the Arduino also seems to work.

Then I decided to create a simple service server which takes request from the std_srvs Empty type. I checked if this type is available with 'rossrv list' (as well as the custom made srv type ModeSelect, which is eventually what I want to include into the service server). The std_srvs/Empty is indeed available:

std_srvs/Empty
helloworld_msgs/ModeSelect

I have adjusted the code to create a service server:

#include <ros.h>
#include <helloworld_msgs/ModeSelect.h>
#include <Arduino.h>
#include <std_srvs/Empty.h>

// Create roscpp's interface for creating subscribers, publishers, etc
ros::NodeHandle n;

// Create a service server that takes nothing and returns nothing
void callback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
{
  // Simulate function running for a non-deterministic amount of time
  delay(random(5,70));
}

void setup()
{
  // Initialize node
  n.initNode();
}

ros::ServiceServer service = n.advertiseService("get_nothing", &callback);

void loop()
{
  n.spinOnce();
  delay(1000);
}

However, if I try to build the package, I get the following error message:

Errors     << helloworld:make /home/mirzam/cmaketut_ws/logs/helloworld/build.make.170.log
make[3]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.
/home/mirzam/cmaketut_ws/src/helloworld/firmware/servernode.cpp:22:1: error: invalid use of template-name ‘ros::ServiceServer’ without an argument list
 ros::ServiceServer service = n.advertiseService("get_nothing", &callback);
 ^
make[6]: *** [CMakeFiles/hello.dir/servernode.cpp.obj] Error 1
make[5]: *** [CMakeFiles/hello.dir ...
(more)
edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
1

answered 2018-12-06 05:57:51 -0500

gvdhoorn gravatar image

updated 2018-12-06 05:58:36 -0500

I believe the issue here is that you're supplying the service name to advertiseService(..).

According to the code of that function, it only accepts a reference to a ServiceServer instance, similar to how you advertise(..) a Publisher or Subscriber in rosserial (see here).

The prototype of advertiseService(..) is actually:

template<class MReq, class MRes, class ObjT>
bool ros::NodeHandle_<Hardware, MAX_SUBSCRIBERS, MAX_PUBLISHERS, INPUT_SIZE, OUTPUT_SIZE>::advertiseService(ros::ServiceServer<MReq, MRes, ObjT>&)

Note there is no char[] or std::string in there anywhere.

To initialise the service server the code should probably be something like:

#include <ros.h>
#include <Arduino.h>
#include <std_srvs/Empty.h>

// Create roscpp's interface for creating subscribers, publishers, etc
ros::NodeHandle n;

// Create a service server that takes nothing and returns nothing
void callback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
{
  // Simulate function running for a non-deterministic amount of time
  delay(random(5,70));
}

ros::ServiceServer<std_srvs::Empty::Request, std_srvs::Empty::Response> service("get_nothing", &callback);

void setup()
{
  // Initialize node
  n.initNode();
  n.advertiseService(service);
}

void loop()
{
  n.spinOnce();
  delay(1000);
}

Note the use of advertiseService(..) in the setup() function, and the declaration of service with the service name and the callback.

edit flag offensive delete link more

Comments

Note btw: I'm not sure it's a good idea to loop at 1 Hz. It could be that this leads to desyncs (buffer overflows due to the low rate of processing events).

gvdhoorn gravatar imagegvdhoorn ( 2018-12-06 06:00:04 -0500 )edit

Thank you for the response! It now works on the Arduino.

Mirzam gravatar imageMirzam ( 2018-12-06 07:48:07 -0500 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

3 followers

Stats

Asked: 2018-11-24 08:08:43 -0500

Seen: 209 times

Last updated: Dec 06 '18