Skip to content

cisstMultiTask tutorial

Anton Deguet edited this page May 27, 2014 · 15 revisions

Table of Contents generated with DocToc

Introduction

In this tutorial we will create two simple components. The first component is a counter. It's main function is to periodically increment an internal counter. When the counter overflows it should send an event. One should be able to query the current value and set the increment. If the user requests an incorrect value for the increment, the counter component will throw an event with an informative message.

The second component user is designed to be connected to the counter component. In this example, we're avoiding using a GUI toolkit to make the code as simple as possible. The user interface is text based.

The latest version of the code for this tutorial can be compiled along the cisst using the CMake options CISST_BUILD_EXAMPLES and CISST_cisstMultiTask_EXAMPLES. The code itself can be found in cisst/cisstMultiTask/examples/tutorial

Counter component

Periodic task

For this component, we're using a the base class mtsTaskPeriodic, i.e. the method used to perform all user defined computations Run will be called periodically and the library will attempt to maintain a constant frequency between calls to the Run method. The amount of jitter depends on the services provided by the Operating System (the cisstOSAbstraction library provides an abstraction layer to the different OSs features).

One of the parameters provided to the constructor is the desired periodicity provided as a double representing the time in seconds. To make sure the code is readable, cisst has a set of constants used to indicate the units used, e.g. 5.0 * cmm_ms indicates 5 milliseconds.

It is possible to use different types of components; continuous, event based, triggered by an external event, ... See all component and task types in cisstMultiTask concepts.

In header file:

#include <cisstMultiTask/mtsTaskPeriodic.h>

class counter: public mtsTaskPeriodic {
    ...
};

In implementation file:

counter::counter(const std::string & componentName, double periodInSeconds):
    // base constructor, same component name and period.  Third
    // parameter is "false" because we don't need hard realtime.  Last
    // parameter, 500, is the size of the default state table
    mtsTaskPeriodic(componentName, periodInSeconds, false, 500),
    ...
{
}

State table

All cisstMultiTask components own at least one state table. A state table can be seen as a matrix where the columns represent a state data object and the rows the values of that data object over time. It is implemented as a circular buffer and is used to provide a thread safe mechanism to publish the component's data (one writer, multiple readers). For historical reasons, all components have a default state table member (StateTable) but users can add as many state tables as they need (using AddStateTable). One can add more state tables to handle:

  • different refresh rates, i.e. some data doesn't change over time. In this example, the increment changes only when set by the user so we don't need to save the data at the same refresh rate as the counter value.
  • similar groups of data, i.e. a component can maintain multiple similar interfaces corresponding to similar devices (e.g. left and right arms of a robot). In this case, one can use two tables containing the exact same data.

In header file, declare data to be added to state table(s) and optionally user defined state tables:

    // internal counter data
    double Counter;

    // increment used for the counter
    mtsStateTable ConfigurationStateTable;
    double Increment;

In implementation file, configuring the state tables:

    // state table variables
    StateTable.AddData(Counter, "Counter");

    // user defined configuration state table
    // first you need to add the state table to the component
    AddStateTable(&ConfigurationStateTable);
    // second, make sure we control when the table "advances"
    ConfigurationStateTable.SetAutomaticAdvance(false);
    // finally, add data to the state table
    ConfigurationStateTable.AddData(Increment, "Increment");

For the user defined state table, since we turned off Automatic Advance, we need to Start and Advance manually:

    // now we can add to the state table
    ConfigurationStateTable.Start();
    Increment = increment;
    // make the circular buffer move one step
    ConfigurationStateTable.Advance();

Commands

explain thread safety for read using state table and ProcessQueuedCommands

Events

explain two types of events, multiple observers and ProcessQueuedEvents

User component

Functions

explain not that not all commands in provided need a function in required. functions in required can be optional.

Event handlers

Connecting components

add, connect, set state and wait

Clone this wiki locally