RTCプログラミングの流れ


RTC プログラミングの流れ

OpenRTM-aist は、コンポーネントを開発したいユーザー(コンポーネントデベロッパ) が持つ既存のソフトウエア資産、あるいは新たに作成したソフトウエアを容易に RTコンポーネント(RTC)化するためのフレームワークを提供します。 コンポーネント作成の大まかな流れは下図のようになります。


ComponentDevelFlow.png
RTコンポーネントの開発フロー


コンポーネントデベロッパーは、既存のソフトウエア資産のライブラリ関数・クラスライブラリ等をコンポーネントフレームワークに埋め込みコンポーネントを作成します。 こうすることで、既存のソフトウエア資源をソフトウエア部品である RTコンポーネントとして作成しておき、様々な場面で再利用することができるようになります。 作成された RTコンポーネントは、ネットワーク上の適切な場所に配置して、分散オブジェクトとしてネットワーク上の任意の場所から利用することができます。

図に示すように、RTコンポーネントフレームワークに則って作成された RTコンポーネントは大きく分けて2つのバイナリファイルとして作成することができます。 スタンドアロン RTコンポーネント (Standalone RT-Component) は、単一ファイルでそのまま実行できる実行形式のバイナリです。 ローダブルモジュール RTコンポーネント (Loadable Module RT-Component) は動的にロード可能なローダブルモジュール形式のバイナリファイルです。 RTコンポーネントはこれらの2つの形式で作成、配布、実行することができます。

RTC プログラミングの基礎

通常のプログラミングと RTコンポーネントのプログラミングには、幾つかの大きな違いがあります。

main関数が無いプログラム

RTコンポーネントのプログラムには通常のプログラムとは異なり、main関数がありません。 代わりに1つの RTコンポーネントは、通常ある特別な基底クラスを継承した一つのクラスとして実装されます。

RTコンポーネントにさせたい処理は、その基底クラスのメンバ関数(メソッド)をオーバーライドする形で記述します。 例えば、初期化のような処理は、onInitialize という関数の中に記述します。あるいは、終了時に行いたい処理であれば、onFinalize という関数の中に記述します。

 ReturnCode_t MyComponent::onInitialize()
 {
   // 初期化処理など
 }
 ReturnCode_t MyComponent::onFinalize()
 {
   // 終了処理など
 }

では、ここで書いた初期化処理や、終了処理はいつ実行されるのでしょうか? それを知るためには、RTコンポーネントのライフサイクルを知る必要があります。

コンポーネント・ライフサイクル

ある RTコンポーネントが生まれてから死ぬまでの一連の流れのことを、コンポーネントのライフサイクルと呼びます。

コンポーネントには基本的に

  • 生成状態(Created)
  • 活動状態(Alive)
  • 終了状態

の3つの状態を持ちます。 (Alive状態は内部にさらに状態を持ちます(後述)。)

コンポーネントは1つのクラスであることは上で述べました。 従って、コンポーネントが生成されるということは、オブジェクト(インスタンス)が生成されることとほぼ同じです。 通常、RTコンポーネントはマネージャ(RTCマネージャ)によって生成され、以後マネージャが RTコンポーネントのライフサイクルを管理します。

具体的には、マネージャは RTコンポーネントのインスタンス生成後、上で述べた onInitialize関数をコールします。 また、RTコンポーネントが終了するとき、マネージャは onFinalize関数をコールします。 このように、RTコンポーネントのライフサイクルの中の特定のタイミングに割り当てられた処理(これをアクションと呼ぶ)毎に、必要な処理を記述することで、RTコンポーネントのプログラミングを行います。

実行コンテキスト

通常プログラムを実行するとスレッドが割り当てられ、そのスレッドがプログラムとして記述された処理を実行します。 ロボットを制御するプログラムでは、通常スレッドにより実行されるループ(制御ループや処理ループ)を持ち、センサーデータを処理したり、アクチュエーターを制御し続けます。 こうした、何かを処理したり制御したりするための主たる処理を RTコンポーネントではコアロジックと呼びます。

RTコンポーネントは、生成され Alive状態になると通常一つのスレッドが割り当てられ、RTコンポーネントとしてのメインの処理(コアロジック)を実行します。 このスレッドを RTコンポーネントでは実行コンテキスト(ExecutionContext)と呼びます。 実際には、実行コンテキストはスレッドそのものではなく、スレッドを抽象的に表現したもので実行周期や状態を持ちます。 つまり、RTコンポーネントが生成されると実行コンテキストが RTコンポーネントに関連付けられ、コアロジックが駆動されることにより、RTコンポーネントが何らかの処理(例えばロボットを制御するなど)を行います。

RTC の状態遷移

上で述べたように、RTコンポーネントは状態を持ち、その状態や遷移に割り当てられたアクションとして処理を記述します。 下図は RTコンポーネントの状態遷移図(UMLのステートマシン図)を表しています。



RTCStateMachine040.png
RTコンポーネントの状態遷移



Created と Alive は RTコンポーネントの状態です。 Alive状態の中にも幾つかの状態が存在しています。

スレッドの停止状態と実行状態

まず、Alive状態内部の上部の Stopped と Running状態から見ていきます。



RTCStateMachineStartStop.png
スレッドの停止状態と実行状態



これは、実行コンテキストをスレッドとして見たとき、スレッドが停止中(Stopped)か実行中(Running)かを表す状態です。

停止状態(Stopped)にある実行コンテキストが startイベントを受け取ると、RTコンポーネントの onStartup を実行して実行状態(Running)に遷移します。 逆に stopイベントにより、実行コンテキストは RTコンポーネントの onShutdown を実行して停止状態(Stopped)状態に遷移します。

コアロジックのアクションは、実行状態(Running)状態のときのみ実行され、停止状態においては全てのアクションは実行されません。

アクティブ・非アクティブ状態

Alive状態内の下段はコアロジックのアクティブ(Active)・非アクティブ(Inactive)・エラー(Error)に関する状態遷移です。

RTコンポーネント生成直後は、RTコンポーネントは非アクティブ状態(Inactive)にあります。 RTコンポーネントをアクティブ化すると、RTコンポーネントのアクションである onActivate がコールされアクティブ状態に遷移します。 アクティブ状態にいる間、通常 RTコンポーネントのアクション onExecute が繰り返し実行され続けます。 通常はこの onExecute内で、RTコンポーネントのメインの処理を行います。 例えば、センサからデータを読み込み他のコンポーネントへ送ったり、他のコンポーネントから受け取ったデータに基づきモータを制御したりといった、ロボットにおいて基本的な繰り返し処理は onExecute に記述することになるでしょう。

RTコンポーネントは非アクティブ化されるか、エラーが発生するまでアクティブ状態に留まり続けます。 非アクティブ化される場合は onDeactivate がコールされ、非アクティブ状態に遷移します。 アクティブ状態の処理の中で何らかのエラーが発生した場合、RTコンポーネントのアクションである onAborting がコールされ、エラー状態(Error)に遷移します。

エラー状態に遷移した場合、外部からリセットが行われるまでエラー状態に留まり続け onError がコールされ続けます。 リセットが行われると、onReset がコールされます。 onReset の処理が成功すれば非アクティブ状態(Inactive)に遷移し、再びアクティブ状態になることが出来ますが、onReset が失敗した場合は、エラー状態に留まり続けます。



RTCStateMachineActiveInactive.png
非アクティブ状態・アクティブ状態・エラー状態



アクションのまとめ

RTコンポーネント開発者の主な仕事は、自分が作成しようとするコンポーネントでは、これまで述べてきた RTコンポーネントの各状態毎にどういった処理をすればよいのかを考え、それぞれのアクションに対応する関数を実装することです。 つまり、自分が作成するコンポーネントに必要なon???という関数だけをオーバーライドし、関数の中身を記述すればいいのです。

以下に、コンポーネントのアクションの関数と役割を示します。

onInitialize 初期化処理、コンポーネントライフサイクルの開始時に一度だけ呼ばれる。
onActivated 非アクティブ状態からアクティブ化されるとき1度だけ呼ばれる。
onExecute アクティブ状態時に周期的に呼ばれる。
onDeactivated アクティブ状態から非アクティブ化されるとき1度だけ呼ばれる。
onAborting ERROR 状態に入る前に1度だけ呼ばれる。
onReset エラー状態からリセットされ非アクティブ状態に移行するときに1度だけ呼ばれる。
onError エラー状態にいる間周期的に呼ばれる。
onFinalize コンポーネントライフサイクルの終了時に1度だけ呼ばれる。
onStateUpdate onExecute の後毎回呼ばれる。
onRateChanged ExecutionContext の rate が変更されたとき呼ばれる。
onStartup ExecutionContext が実行を開始するとき1度だけ呼ばれる。
onShutdown ExecutionContext が実行を停止するとき1度だけ呼ばれる。

ダウンロード

最新バージョン : 2.0.1-RELESE

統計

Webサイト統計
ユーザ数:2159
プロジェクト統計
RTコンポーネント307
RTミドルウエア35
ツール22
文書・仕様書2

Choreonoid

モーションエディタ/シミュレータ

OpenHRP3

動力学シミュレータ

OpenRTP

統合開発プラットフォーム

産総研RTC集

産総研が提供するRTC集

TORK

東京オープンソースロボティクス協会

DAQ-Middleware

ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク