Flow of RTC development

// Title: Flow of RTC development

This section explains how to develop RT-Components using RT-Middleware (OpenRTM-aist).

Development flow

OpenRTM-aist consists of a framework for componentization and middleware for managing/executing components.

OpenRTM-aist provides a framework for an easy way for the user (component developer) to convert existing user-owned software assets and newly developed software to RTC. A rough flow of component creation is as follows.

RTC and RT system development flow

As mentioned above, the code related to the common interface of the RT component, the processing of exchanging data with other components, etc. are hidden by the RT component framework. Since these processes are common, many portions of an RTC can be created as libraries or automatically generated. OpenRTM-aist provides RTCBuilder as a tool for generating an RTC base code.

RTC developers build RT-Components by incorporating existing programs developed by themselves into the component framework and build robot systems by combining multiple RTCs. Once you make RTCs by using existing software resources as software parts, you can reuse them in many situations. Also, a created RTC can be put on a network node and can be used from other network nodes.

RTC created according to the RTC framework can roughly be divided into two types - Standalone RTC (Standalone RT-Component) and Loadable module RTC (Loadable Module RT-Component). Standalone RTC is an executable binary file. Loadable module RTC is a dynamically loadable binary file and used for the case where multiple RTCs are executed at the same time in a single process.

Creating model code with RTCBuilder

RTCBuilder is a development tool that automatically generates a base code of RT component. Most of the code other than the core logic is generated automatically by entering information on the basic profile and information about the data port, the service port, and the configuration. Supporting languages are C ++, Java, Python, and Lua. Before creating the component, we decide the following things.

  • Profile (name, category name, version etc.)
  • Data port (InPort/OutPort, port name, data type)
  • Service port (port name, service interface)
  • Configuration (variable name, variable type)

Open a dialogue by selecting [File]> [New]> [Other] from the Eclipse menu. Then, select "RTCBuilder" from "Others" in the tree pane and then click Next". Enter the project name and click [Finish]. The following figure screen is displayed, RTCBuilder has tab pages - "Basic", "Activity", "Data Ports", "Service Ports", "Configuration", "Documentation", "Language and Environment" and "RTC.xml". Fill in the items as needed on the page tabbed from "Basic" to "Language and Environment", finally click the "Code Generation" button on the "Basic" tab page to generate the base code. The generated code is saved under the folder of the project name in the workspace specified when Eclipse is started.

RTCBuilder development screen

Implementation of RTC

Unlike ordinary programmings, RT component programming do not directly implement processes in the main function. I will describe an RTC implementation example of a C ++ case.

An RT component is implemented as a class that inherits a base class. In the RT component, the processing performed by the core logic is programmed by overriding the member function (method) of the base class. For example, the processing to be performed at the initialization time is programmed in onInitialize function, the periodically executing process at an active time is programmed in onExecute function.

 class MyComponent
  : public DataflowComponentBase
   // What we want to execute at initialization
   virtual ReturnCode_t onInitialize()
     if (mylogic.init())
       return RTC::RTC_OK;
     return RTC::RTC_ERROR;
   // Process to be executed periodically
   virtual ReturnCode_t onExecute(RTC::UniqueId ec_id)
     if (mylogic.do_someting())
       return RTC::RTC_OK;
   MyLogic mylogic;
   // Declaration of port etc.
   //   :

The above is a C++ implementation example. In this example, the class declaration and the implementation are written in a program. But in actual, the generated source codes are separated into a header file (.h) and an implementation file (.cpp). The object mylogic of the MyLogic class is an instance of the class in which the core logic is implemented. In the example, RTC is implemented by calling the mylogic member function very simply, even in the actual implementation, it is recommended to implement the core logic in a class which can be used easily in such a manner in advance, Also, it is recommended that the number of calls in the call back function is minimum.

RTCBuilder also generates several files (Makefile/Project file) at the same time as the base code generation. By compiling/building process with using the files, an executable file or a shared object (or DLL) file is generated.

RTC life cycle

As described in the above, in the implementation of the RTC, a component is created by programming the required process in a predetermined function (callback function). To know what kind of function is called and at what timing it is called, it is necessary to understand the state transition of RTC, that is, life cycle. The figure below shows the RTC state transition diagram.

RTC Life Cycle (UML State Machine Diagram)

A component has the following states.

  • Created state (Created)
  • Alive state (Alive)
    • Inactive state (Inactive)
    • Active state (Active)
    • Error state (Error)
  • Exit state

At each of these states and transitions, a predetermined function (callback function) is called by an EC. The table shows the callback functions and the timing when each is called.

Function name Overview
onInitialize Called only once at the life cycle initialization.
onActivated Called once when activated.
onDeactivated Called once when deactivated.
onExecute Called periodically in active state.
onStateUpdate Called after every onExecute.
onAborting Called once when enter to the error state.
onError Called periodically when in error state.
onReset Called once when returning from error state.
onShutdown Called once when EC driving stops.
onStartup Called once when EC driving starts.
onFinalize Called only once at the end of the life cycle.