Orocos/ROS Services tutorial¶
This tutorial will teach how to set up an Orocos component to expose its Operations as ROS services.
Note
If you don’t have a working version of Orocos + ROS installed in your system, please refer to the first tutorial Installation.
These tutorials assume you have a working knowledge of Orocos components, if not read The Orocos Component Builder’s Manual or follow the basic RTT tutorials.
In this tutorial we will show you how to expose the operations of your Orocos component as ROS services.
In general the signature of the operation you want to expose as a ROS service will have to adhere to the typical ROS service callback:
bool operation(Service::Request&, Service::Response&);
Note
If you want to use custom ROS services, see Defining custom messages.
Take for example the following component:
Header file:
#ifndef STANDARDCOMPONENT_H
#define STANDARDCOMPONENT_H
#include <rtt/RTT.hpp>
#include <rtt/Component.hpp>
#include <my_msgs/MyService.h>
class StandardComponent:
public RTT::TaskContext
{
public:
/// Constructor
StandardComponent(std::string const& name);
/// Destructor
~StandardComponent(){}
bool myOperation(my_msgs::MyService::Request& request, my_msgs::MyService::Response& response)
{
response.success = false;
if (request.data)
{
response.success = true;
}
return true;
}
/// Configure
bool configureHook();
/// Update
void updateHook();
};
#endif // StandardComponent_H
And cpp file:
#include <orocos-ros-services/StandardComponent.h>
StandardComponent::StandardComponent(std::string const& name)
: RTT::TaskContext(name)
{
this->provides("simple_service")->addOperation("myOperation", &StandardComponent::myOperation, this, RTT::ClientThread);
}
bool StandardComponent::configureHook()
{
return true;
}
void StandardComponent::updateHook()
{
RTT::log(RTT::Info) << "Waking up!" << RTT::endlog();
}
ORO_CREATE_COMPONENT(StandardComponent)
That exposes an operation using the MyService
type from the my_msgs
package.
We can deploy with the following script:
import("orocos-ros-services")
import("rtt_rosnode")
import("rtt_roscomm")
import("rtt_std_srvs")
import("rtt_my_msgs")
loadComponent("my_component", "StandardComponent")
// load the rosservice service in the component
loadService("my_component", "rosservice")
// connect the operation to the ros service:
my_component.rosservice.connect("simple_service.myOperation", "/my_namespace/my_operation", "my_msgs/MyService")
Operations can also be exposed as ROS services without having to adher to the typical
bool operation(Service::Request& request, Service::Response& response)
interface, with
the use of wrappers. For the services in std_srvs
the following operation signatures are
supported:
std_srvs/Empty:
- bool empty() // The service call fails if empty() returns false!
// Use std_srvs/Trigger if the result should be returned as the response.
- void empty()
std_srvs/SetBool:
- bool setBool(bool, std::string &message_out)
- bool setBool(bool) // response.message will be empty
- std::string setBool(bool) // response.success = true
- void setBool(bool) // response.success = true and response.message will be empty
std_srvs/Trigger:
- bool trigger(std::string &message_out)
- bool trigger() // response.message will be empty
- std::string trigger() // response.success = true
This can be extended to other ros service types, see the header files in the rtt_std_srvs package.