Hello world 2 - RTT Tutorial: Properties¶
The source code of this tutorial can be found in the GitHub repository.
It is recommended to read The Attributes and Properties Interface before starting this tutorial.
In this tutorial we will create a HelloWorld
component, and add some properties, attributes, and constants,
and show how to use them.
Contents of HelloWorld.cpp
:
/**
* @file HelloWorld.cpp
* This file demonstrates the Orocos 'Property' and 'Attribute' primitives with
* a 'hello world' example.
*/
#include <rtt/os/main.h>
#include <rtt/Logger.hpp>
#include <rtt/TaskContext.hpp>
#include <rtt/Activity.hpp>
/**
* Include this header in order to use properties or attributes.
*/
#include <rtt/Property.hpp>
#include <rtt/Attribute.hpp>
#include <rtt/Component.hpp>
#include <rtt/marsh/Marshalling.hpp>
using namespace std;
using namespace RTT;
namespace Example
{
/**
* Every component inherits from the 'TaskContext' class. This base
* class allow a user to add a primitive to the interface and contain
* an ExecutionEngine which executes application code.
*/
class Hello
: public RTT::TaskContext
{
protected:
/**
* @name Name-Value parameters
* @{
*/
/**
* Properties take a name, a value and a description
* and are suitable for XML.
*/
std::string property;
/**
* Attributes are C++ variables exported to the interface.
*/
double attribute;
/**
* Constants are not changeable by an outsider, only by us.
*/
std::string constant;
/** @} */
public:
/**
* This example sets the interface up in the Constructor
* of the component.
*/
Hello(std::string name)
: TaskContext(name),
// Name, description, value
property("Hello World")
{
// Now add it to the interface:
this->addProperty("my_property", property).doc("This property can contain any friendly string.");
this->addAttribute("my_attribute", attribute);
this->addConstant("my_constant", constant);
/* OPTIONAL
this->getProvider<Marshalling>("marshalling");
*/
}
bool configureHook()
{
/* OPTIONAL
if ( this->getProvider<Marshalling>("marshalling")->readProperties("hello.xml") == true ) {
log(Info) << "The property value is now: " << property << endlog();
} else {
log(Warning) << "No hello.xml property file present yet !" << endlog();
}
*/
return true;
}
void cleanupHook()
{
/* OPTIONAL
this->getProvider<Marshalling>("marshalling")->writeProperties("hello.xml");
*/
}
};
}
ORO_CREATE_COMPONENT( Example::Hello )
Tutorial 2¶
Note
This tutorial assumes that you have installed Orocos through the pre-compiled packages distributed via ROS in Ubuntu. If you don’t have it installed, try following the instructions from Installation options.
First, compile and run this application.
Note
ROS is not needed to run Orocos or to follow this tutorial, but it is a convenient way to quickly get started.
# You can change the next two settings in accordance to your setup export RTT_TUTORIALS_WS=${HOME}/orocos_tutorials_ws export ROS_DISTRO=kinetic # Get the repository with the exercises on place mkdir -p ${RTT_TUTORIALS_WS}/src cd ${RTT_TUTORIALS_WS}/src git clone https://github.com/orocos-toolchain/rtt_examples.git cd .. # Build the examples using ROS catkin tools source /opt/ros/${ROS_DISTRO}/setup.bash catkin build
Properties, attributes, and constants can be used to expose members of a TaskContext,
and do so each in a different way. You can add them, and give them a name using the
addProperty
, addAttribute
, and addConstant
functions as shown above.
Let’s run the application with the Orocos deployer:
The start.ops
file for the deployment (run with deployer-gnulinux -lInfo start.ops
):
import("hello_2_properties")
loadComponent("hello", "Example::Hello")
// Inspect the interface of the "hello" component:
ls hello
You can see the property string listed under Configuration Properties
, and the attribute and constant
we added can be found under Attributes
in the output of ls hello
.
The value of the property and attribute can be changed in the deployer interface:
hello.property = "My new property value"
hello.attribute = 2.0
The value of the constant can of course not be changed.
Unlike attributes, properties can be written to an xml file for persisten storage. The marshalling
service is required to do that. You can either load the service in the hello
TaskContext with the
Orocos deployer, and read and write the properties to an xml file like this:
loadService("hello", "marshalling")
You can inspect the interface of the marshalling service as follows:
hello.marshalling
Reading and writing properties to an xml file can then be done using the readProperties
and writeProperties
functions:
// Writes to XML:
hello.writeProperties("hello.xml")
// Reads from XML:
hello.readProperties("hello.xml")
You can add these instructions to the start.ops
file to make them permanent.
The other way to do this is to load the service in the constructor of the TaskContext:
Hello(std::string name)
: TaskContext(name),
// Name, description, value
property("Hello World")
{
// Now add it to the interface:
this->addProperty("my_property", property).doc("This property can contain any friendly string.");
this->addAttribute("my_attribute", attribute);
this->addConstant("my_constant", constant);
// load the marshalling service
this->getProvider<Marshalling>("marshalling");
}
Then you can read and write the properties in respectively the configureHook
and cleanupHook
.
bool configureHook()
{
// Read properties from xml file
if ( this->getProvider<Marshalling>("marshalling")->readProperties("hello.xml") == true ) {
log(Info) << "The property value is now: " << property << endlog();
} else {
log(Warning) << "No hello.xml property file present yet !" << endlog();
}
return true;
}
void cleanupHook()
{
// write properties to xml file
this->getProvider<Marshalling>("marshalling")->writeProperties("hello.xml");
}
Note
Open question: Would you prefer to hard-code this property reading/writing or would you prefer to script it ?