the Robot Construction Kit


The following example uses orocos.rb’s functionality to manage processes. While it works only for deployments generated using oroGen, the rest of the functionality is available for any RTT component.

This page will go through the steps needed to write a startup/monitoring script for a system based on Orocos/RTT components. It assumes that the components are generated by the oroGen component generator (and will give snippets of the associated oroGen declarations).

First of all, every orocos.rb scripts need to start with

require 'orocos'
include Orocos


It loads the orocos.rb library and initializes the CORBA communication layer.

Starting processes and setting up modules

Now, let’s assume that the deployments you have look like this:

deployment "lowlevel" do
  task('can', "can::Task").
  task("hbridge", "hbridge::Task")
deployment "imu" do
  task('imu', 'imu::XsensTask')
deployment "gps" do
  task('gps', 'dgps::Task')
deployment "hokuyo" do
  task('hokuyo', 'hokuyo::LaserAcquisition')
deployment "state_estimator" do
  task 'stateEstimator', 'state_estimator::StateEstimator'

I.e., you have 5 deployments (Unix binaries), with up to three components in them (add_default_logger adds a base::Logger component in the deployment). To use these deployments, one would do: 'lowlevel', 'imu', 'gps', 'hokuyo', 'state_estimator' do
  # Here goes the supervision code

where the names given to are the deployment names, i.e. the name given to the “deployment” statement.

This starts all the processes, and wait for them to be ready to be used. The advantage of this method is that, whenever you leave the do … end block (for instance because of an error in the Ruby program), all the processes will be stopped properly.

Now, let’s configure and start the imu driver. To do that, you need to get a handle on the imu::XsensTask task that is declared in the imu deployment. You achieve this by using the task name – i.e. the name given to the ‘task’ statement: 'lowlevel', 'imu', 'gps', 'hokuyo', 'state_estimator' do
  imu = Orocos.name_service.get 'imu'
  pose_estimator = Orocos.name_service.get 'poseEstimator'
  # From this point on, the 'imu' variable represents the XsensTask task
  # context, and can be used to manipulate it.

The value returned by Orocos.name_service.get is an instance of {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::TaskContext”}}

The task name is the first argument of the ‘task’ statements in the deployment definitions:

  task('imu', 'imu::XsensTask')

Now, let’s look at the definition of the XsensTask task context.

task_context 'XsensTask' do

  property('port', '/std/string', "").
    doc 'the device port'

  property('max_timeouts', 'int').
    doc 'number of consecutive timeouts after which an error is raised'

  output_port('imu_readings', '/base/IMUReading').
    doc 'provides timestamped IMUReading samples containing orientation and calibrated sensor values.'

We can see that the drivers needs to be configured (it starts in the PreOperational state and the ‘configure’ method must be called on it). Moreover, it has a string propery called ‘port’ that allows to specify what device file can be used to communicate with the IMU. In Ruby, the properties are simply read and written with

  puts imu.port # displays the current value of the port property
  imu.port = '/dev/ttyS1' # sets a new value for the port

Then, the configuration transition is done by calling #configure. Our script now looks like: 'lowlevel', 'imu', 'gps', 'hokuyo', 'state_estimator' do
  imu = Orocos.name_service.get 'imu'

  imu.port = '/dev/ttyS1'
  # From this point on, the IMU is ready to be used.

It can then be started with TaskContext#start: 'lowlevel', 'imu', 'gps', 'hokuyo', 'state_estimator' do
  imu = Orocos.name_service.get 'imu'

  imu.port = '/dev/ttyS1'
  # The IMU is configured and runs

Then, the actual state of the module can be checked with {rdoc_class: TaskContext#running?}, #error? and #fatal?. It can be manipulated with #configure, #start, #stop, #reset_error, and #cleanup

Connecting modules together

In our example, the state_estimator module is a Kalman filter that processes the IMU and GPS streams. We therefore need to connect the outputs of the imu and gps tasks to the corresponding inputs of the state estimator module.

To do that, we use the {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::OutputPort#connect_to”}} method:

  imu = Orocos.name_service.get 'imu'
  gps = Orocos.name_service.get 'gps'
  state_estimator = Orocos.name_service.get 'state_estimator'
  imu.imu_readings.connect_to state_estimator.imu_readings
  gps.position_readings.connect_to state_estimator.position_readings

Advanced topics w.r.t. data connections are covered here.

Inspecting the module output

To read data that comes out of the module, one gets a reader object. This object allows to get samples out and access them from Ruby:

imu_reader = imu.imu_readings.reader

# Display samples that get out of the IMU
# See base/base/imu_readings.h for the definition of base::IMUReading
while true
  sleep 0.1
  if sample =
    orientation = sample.orientation
    puts "[#{", ")}] #{}"

In the above code snippet, imu.imu_readings is a {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::OutputPort”}} instance and imu_reader is a {rdoc_class: {base_url: /api/tools/orocos.rb, name: “Orocos::OutputReader”}} instance.

A complete description of the manipulation of ports can be found here

We’re done !

The complete script can be found here. Note that it can safely be interrupted with Ctrl+C: we use, and therefore the processes will be cleanly killed on interrupt.