Rock

the Robot Construction Kit

Go to master Flavor stable
Deployments

In orogen, each deployment is a separate binary (UNIX process) in which a certain number of tasks have been instanciated. In other words, certain task contexts classes are tied to a thread and one or multiple triggering mechanisms.

This page will deal with the generics of deployment. The different triggering mechanisms are developed later in this guide.

The deployment block

Each deployment block declares one binary. For instance:

deployment "test" do
  <deployment statements>
end

will generate a “test” binary. By default, it will be installed by CMake. If that is not desired, for instance if it is for testing purposes only, add the do_not_install statement in the block:

deployment "test" do
  do_not_install
  <other deployment statements>
end

In the block, the following conditions can be tested:

  • the target OS. You can use the xenomai? and gnulinux? predicates to enable/disable some parts based on the target OS.
  • the fact that the binary will be interfaced with CORBA or not. Use the corba_enabled? predicate to test this. CORBA is the target if the --corba flag is given to orogen during generation, or if the enable_corba statement is added in the deployment block. It is also possible to forcefully disable it by adding the disable_corba statement in the deployment.

Instanciating tasks

The basic thing to be done in a deployment is listing the tasks that should be instanciated. It is done by using the ‘task’ statement:

  task 'TaskName', 'orogen_project::TaskClass'

It will create a task with the given name and class. By default, that task will have its own thread.

Threading

There are mainly two options with respect to threading. In the first case, when a task is triggered, the associated thread is woken up and the task will be asynchronously triggered in its own thread when the OS scheduler decides to do so. It is the safest option (and the default) as the different tasks are made independent from each other.

In the second case, the task does not have its own thread. Instead, the thread that triggers it will be used to run the task. In other words, task triggering stops to be asynchronous, but instead is seen as a method call. This is mainly useful for tasks that are triggered by data coming in their input port (this triggering mechanism is described here). The main advantage is that the OS scheduler is removed from the equation, which can reduce latency.

The first case does not requires a specific declaration in the deployment block. Nonetheless, the underlying thread can be parametrized with a scheduling class (realtime/non-realtime) and a priority. By default, a task is non-realtime and with the lowest priority possible. Changing it is done with the following statements:

  task('TaskName', 'orogen_project::TaskClass').
    realtime.
    priority(<priority value>)

Note the dot at the end of the first two lines. It is important and not adding it would lead to a NoMethodError error during generation.

The priority value being a number between 1 (lowest) and 99 (highest). Moreover, note that the periodic and IO triggering mechanisms require the task to be in its own thread.

The second case is called a sequential activity and is declared with:

  task('TaskName', 'orogen_project::TaskClass').
    sequential

Initial setup of the generated deployment

It is possible to statically specify an initial setup of the task contexts present in the deployment.

First, it is possible to set simple properties. To do so:

my_task.property = new_value

where new_value is compatible with the property’s type. It works only for simple types (like numbers or strings), where new_value is the corresponding ruby literal.

Logger integration

If you installed orogen’s logger component, specific statements are made available to you in the deployment block.

First, the add_default_logger statement would create a logger task (i) whose name is deploymentname_Logger and (ii) which log file is deploymentname.log. This convention is used by orocos.rb, for instance, to implement automated logging setup.

If this default logger does not suit you, you can also add specific loggers with:

logger("file name", "task_name").
    report(other_task.output_port_name).
    report(third_task.another_output_port)