Copyright © 2006,2007 Peter Soetens, FMTC
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation, with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of this license can be found at http://www.fsf.org/copyleft/fdl.html.
Table of Contents
This document describes the Orocos OCL::DeploymentComponent for loading and configuring other components using an Orocos script or XML file. This component can only load components into the same process.
Each Orocos component can be compiled as a shared, dynamic loadable library. Each such library can define a special function which will allow the DeploymentComponent to create new instances of a component type. This principle is analogous to the plugin mechanism found in web browsers or other desktop applications.
A common usage scenario of the DeploymentComponent goes as follows. An initial Orocos application is created which contains only the DeploymentComponent and the OCL::TaskBrowser. When the application is started, the TaskBrowser prompts for commands which can be given to the DeploymentComponent.
Figure 1. Component Deployment Overview

Components are located on your disk using the 'import' statement, loaded using 'loadComponents' and configured using 'configureComponents'. These three steps can be described in an XML file format or using the command prompt.
Figure 1, “Component Deployment Overview” shows the basic
steps. An XML file contains instructions for the
DeploymentComponent where to look for components ('import
statements'), which component types to create, which name they
must be given and how their internal thread is configured
(priorities, periods,...). Furthermore this file describes the
network interconnections between all components and how data
must be relayed from one component to another. The
loadComponents("file.xml") method
reads this file, looks up the components, creates them and
stores the configuration parameters. One can apply the
configuration (threads, properties, data connections,...) by
calling configureComponents(). After this
step, the components (and the application as a whole) can be
started.
The configuration does not need to be stored in XML format. One can apply the same configuration by using the scripting methods of the DeploymentComponent at the console prompt, or by listing them in an Orocos script.
Figure 2. Deployment Procedure

The Deployment component API consists of import, loadComponents, configureComponents and startComponents.
The configuration format defines the instructions one can use to load and configure Orocos components. One can divide the instructions in three groups:
Where to look for component libraries
Which components to create and with which name
How each component is setup
Let's demonstrate this principle with a simple application example as shown in Figure 3, “Deployment Example Application”. We want to setup an application with three components: a Reporting component, a 'Controller' and a 'Plant'. The Plant component provides access to the hardware, the Controller component contains the control algorithm. The Reporting component is here to sense the values exchanged and write them to a file.
Figure 3. Deployment Example Application

A Reporter component monitors communication between Plant and Controller. The Deployment component itself is not shown.
The import statement causes all
component libraries in a given directory to be pre-loaded.
It does not cause any component to be created, but
allows the OCL::DeploymentComponent to know where the
component libraries are located. This function works recursively
and may be called for multiple paths.
In XML, the import statement looks like:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "cpf.dtd"> <properties> <!-- .... --> <simple name="Import" type="string"><value>/usr/local/lib</value></simple> </properties>
The script method equivalent is:
import("/usr/local/lib")
Each library found under the given location is pre-loaded. The import statement allows you to load non-Orocos libraries as well. If a library contains one or more Orocos components, the contained component types become available in the next step.
To see the effects of the import function, the available
types can be queried by invoking the
displayComponentTypes (script) method:
(type 'ls' for context info) :displayComponentTypes()
Got :displayComponentTypes()
= I can create the following component types:
OCL::ConsoleReporting
OCL::FileReporting
(void)
Import makes components available, but does not create an
specific instance yet. In order to add
a component of a given type to the current application,
use the loadComponent function:
In XML, the loadComponent statement of a reporting component would look like:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "cpf.dtd"> <properties> <!-- ... import statements locate Orocos reporting library ... --> <simple name="Import" type="string"><value>/usr/local/lib</value></simple> <struct name="Reporter" type="OCL::FileReporting"> </struct> </properties>
This line causes the DeploymentComponent to look up the OCL::FileReporting type, and if found, creates a component of that type with the name "Reporter". This component is added as a peer component to the DeploymentComponent such that it becomes immediately available to the application. This step can be repeated any number of times with any number of types.
Alternatively, the type may be a filename if that file
contains only one component, which is exported using
the createComponent function.
The script method equivalent is:
loadComponent("Reporter", "OCL::FileReporting")
Now that one or more component instances are created, you can configure them by connecting components, assigning threads, configuration values and program scripts. Again, you can do this using XML or the scripting language.
In XML, one adds additional elements to the component struct.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "cpf.dtd">
<properties>
<simple name="Import" type="string"><value>/usr/local/lib</value></simple>
<struct name="Reporter" type="OCL::FileReporting">
<struct name="Activity" type="PeriodicActivity">
<simple name="Period" type="double"><value>0.005</value></simple>
<simple name="Priority" type="short"><value>0</value></simple>
<simple name="Scheduler" type="string"><value>ORO_SCHED_OTHER</value></simple>
</struct>
<simple name="PropertyFile" type="string"><value>file-reporting.cpf</value></simple>
<struct name="Peers" type="PropertyBag">
<simple type="string"><value>Controller</value></simple>
</struct>
</struct>
<struct name="Controller" type="ControllerType">
<struct name="Activity" type="PeriodicActivity">
<simple name="Period" type="double"><value>0.001</value></simple>
<simple name="Priority" type="short"><value>99</value></simple>
<simple name="Scheduler" type="string"><value>ORO_SCHED_RT</value></simple>
</struct>
<simple name="AutoConf" type="boolean"><value>1</value></simple>
<simple name="AutoStart" type="boolean"><value>1</value></simple>
<simple name="PropertyFile" type="string"><value>controller.cpf</value></simple>
<struct name="Ports" type="PropertyBag">
<simple name="SensorValues" type="string"><value>SensorValuesConnection</value></simple>
<simple name="SteeringSignals" type="string"><value>DriveConnection</value></simple>
</struct>
<struct name="Peers" type="PropertyBag">
<simple type="string"><value>Plant</value></simple>
</struct>
<simple name="ProgramScript" type="string"><value>controller-program.ops</value></simple>
<simple name="StateMachineScript" type="string"><value>controller-states.ops</value></simple>
</struct>
<struct name="Plant" type="PlantType">
<struct name="Activity" type="NonPeriodicActivity">
<simple name="Priority" type="short"><value>0</value></simple>
<simple name="Scheduler" type="string"><value>ORO_SCHED_RT</value></simple>
</struct>
<simple name="AutoStart" type="boolean"><value>1</value></simple>
<struct name="Ports" type="PropertyBag">
<simple name="Position" type="string"><value>SensorValuesConnection</value></simple>
<simple name="Velocity" type="string"><value>DriveConnection</value></simple>
</struct>
</struct>
</properties>
The first section of all three components sets up the active
behaviour of the component. Both have periodic activities,
which run with a given period, priority and in a
scheduler. The Controller and Plant run in a real-time scheduler, the
Reporter doesn't. The activities are created and attached to
each component during the
configureComponents() step of the
DeploymentComponent.
The next section of the Controller contains the AutoConf and AutoStart
elements. If AutoConf is set to 1, the DeploymentComponent will call
the component's configure() method during configureComponents(),
after the properties are loaded. If AutoStart is set to 1, the component's start()
method will be called during startComponents().
The PropertyFile section specifies from which file each component is
configured. The CPF files contain XML properties as well
which are read during the
configureComponents() step of the
DeploymentComponent.
The last section of the Reporter component lists its
peers. The Reporter has one peer, the Controller, with which
it will be able to communicate and monitor its data
ports. The Controller component has the Plant as peer, which
means it can control it. It has two data ports listed as
well (SensorValues and SteeringSignals), which are added to
two connection objects. These connections show up in the
Plant component's Ports section as well. And it shows that
the SensorValues Port is connected to the Position Port and
the SteeringSignals Port is connected to the Velocity
Port. If other component's ports in the same file refer to
the same connection object, the ports are connected to each
other by the DeploymentComponent during the
configureComponents() step.
The Component Builder's Manual goes into detail about
the possible connection mechanisms.
The Controller has at the end two additional elements
describing which script files must be loaded into that
component. Both Orocos program scripts and state machine
scripts can be loaded. This is again done during the
configureComponents() step.
This section explains how to prepare a component library for deployment. It is demonstrated with an example.
There exist three C macros for preparing a component
library. The simplest way is when the resulting library
will contain only one component type. Assume we have written
the OCL::HelloWorld component ( in
the OCL C++ namespace) which is compiled in the
orocos-helloworld.so library. The
following code is added to HelloWorld.cpp:
#include "HelloWorld.hpp"
#include <ocl/ComponentLoader.hpp>
/* ... Hello World implementation file ... */
// You must specify the namespace:
ORO_CREATE_COMPONENT( OCL::HelloWorld )This macro inserts a function into the library which will allow the DeploymentComponent to create OCL::HelloWorld components.
In case multiple components are defined in the same
library, two other macros must be used. One macro for each
component type and one macro once for the whole
library. Say your library has components
NS::ComponentX and
NS::ComponentZ in namespace NS. In
order to export both components, you could write in
ComponentX.cpp:
#include "ComponentX.hpp" #include <ocl/ComponentLoader.hpp> /* ... ComponentX implementation file ... */ // once: ORO_CREATE_COMPONENT_TYPE // For the ComponentX type: ORO_LIST_COMPONENT_TYPE( NS::ComponentX )
and in ComponentY.cpp the same but without the
ORO_CREATE_COMPONENT_TYPE macro:
#include "ComponentY.hpp"
#include <ocl/ComponentLoader.hpp>
/* ... ComponentY implementation file ... */
// For the ComponentY type:
ORO_LIST_COMPONENT_TYPE( NS::ComponentY )For each additional component in the same library, the ORO_LIST_COMPONENT_TYPE macro is added. It is allowed to put all the ORO_LIST_COMPONENT_TYPE macros in a single file.
In order to have a working library, care must be taken of the compilation flags. You may compile your library static or shared. But a static library will not be dynamically loadable. In the final executable the DeploymentComponent will be able to find the linked in components and setup the application using the XML file.
The macros need some help to figure out if you are compiling a shared or static library. You need to define the OCL_DLL_EXPORT macro when compiling for a shared library. If this macro is not defined, it is assumed that you are compiling for a static library.
The compilation flag of a component for a shared library might look like:
CFLAGS= -O2 -Wall -fPIC -DOCL_DLL_EXPORT LDFLAGS= -fPIC
The compilation flag of a component for a static library lacks both options :
CFLAGS= -O2 -Wall LDFLAGS=