コンフィギュレーション (基礎編)

コンフィギュレーションとは

ロボットシステムを構築するうえで、システムの外部環境、使用状況や、個別 のデバイス、ロボットの特性に応じて作成するプログラム内のパラメータを変 更ことが度々あります。単純な実験をするための簡単なプログラムでは、パラ メータをハードコード(埋め込んで)して、変更する度に直接書き換え、コンパ イルすることで対処できるかもしれません。もう少し進んで、パラメータをファ イル等から読み込んだり、コマンドライン引数で渡したり等の工夫をすること で再利用性はぐっと高くなります。一つのプログラムを用途に応じて再利用す るためには、こうしたパラメータを埋め込まずに外部化することが非常に重要 になってきます。

RTコンポーネントによって構築されるRTシステムでは、様々な人が作った多様 なコンポーネントが協調して動作しますので、コアロジック内部で使用される パラメータをユーザが自由に定義し、実行時に外部から変更するための機能が 用意されています。これをコンフィギュレーション(機能)と呼びます。コンフィ ギュレーションは複数のパラメータセットを持つことができ、パラメータセッ トを一斉に入れ替えることもできます。パラメータを予め変更可能にしておく ことで、RTCを様々なシステムで簡単に再利用することができます。

configuration_example_ja.png
コンフィギュレーションの例

このセクションでは、RTコンポーネントの重要な機能の一つであるコンフィギュ レーションについて、仕組みと実際の使い方について説明していきます。

コンフィギュレーションの仕組み

下図はコンフィギュレーションの大まかな仕組みを表しています。

configuration_functionality_ja.png
コンフィギュレーションの仕組み

パラメータの名前のペアをコンフィギュレーションパラメー タと呼びます。一つのコンポーネントは複数のコンフィギュレーションパラ メータを定義することができ、その集合をコンフィギュレーションセット と呼びます。

さらに一つのコンポーネントは複数のコンフィギュレーションセットを持つこ とができ、そのうち一つのコンフィギュレーションのみが、実際のパラメータ の値となります。このコンフィギュレーションセットを、アクティブコンフィ ギュレーションと呼びます。コンフィギュレーションセットは名前を付ける ことができ、その名前により区別されます。

外部のツール (RTSystemEditorやrtshell等) を利用して、個々のパラメータ、 あるいはアクティブなコンフィギュレーションセットを変更することができま す。コンフィギュレーションの内容は、コンフィギュレーションに結び付けら れた変数 (パラメータ変数) に反映され、RTコンポーネント内のロジック で使用することができます。こうして、ロジック内部で使用されるパラメータ を外部から容易に変更できるようにすることでコンポーネントの再利用性を高 めることができます。

  • コンフィギュレーション: コンポーネント内のパラメータを外部化するためのRTCの機能
  • コンフィギュレーションパラメータ: 実際にコンポーネント内の外部化されるパラメータ。キーと値から構成される。
  • コンフィギュレーションセット: キーと値のリストから構成される、パラメータのリスト。RTCは複数のセットを持つことができる。
  • コンフィギュレーションセット名: コンフィギュレーションセットにつけられた名前。セットはそれぞれ名前で区別される。
  • アクティブコンフィギュレーション: RTCは複数のコンフィギュレーションセットを持つことができ、そのうち実際にパラメータに反映される有効なセットをアクティブコンフィギュレーションと呼ぶ。
  • パラメータ変数: コンフィギュレーションパラメータに結び付けられた変数。コンフィギュレーションの内容が変更されると変数に代入されている値が変更されます。

型のある言語では、コンフィギュレーションパラメータはその言語で利用可能 な型であればどのような型でもパラメータとして利用することができます。も ちろん、型のない言語でも同様ですが、重要な点は、こうしたパラメータを外 部から設定する際には、その値は文字列によって与えられるということです。

コンフィギュレーションは、文字列をそれぞれのパラメータ型に変換して、実 際の変数にセットします。構造体や配列など、文字列からデータに簡単には変 換できないようなデータ型でも、変換関数を定義することで、どのような型の データでも同じように扱うことができます。これは、予めIDL定義が必要なデー タポートやサービスポートとは大きく異なる点です。

パラメータを定義する

RTコンポーネント内で利用するパラメータを定義する方法にはいくつかあります。

  • RTCBuilderでコンポーネント設計時に定義する
  • rt-templateでコンフィギュレーションパラメータを定義する
  • 手動で必要なコードを書く

以下では、それぞれの方法について説明します。

RTCBuilderによる定義

コンフィギュレーションパラメータを定義するもっとも簡単な方法はRTCの設計 ツールであるRTCBuilderで、RTC設計時にコンフィギュレーションパラメータを 定義することです。

下図はRTCBuilderのコンフィギュレーションの定義画面です。この画面で必要 なパラメータを定義することで、コンフィギュレーションパラメータを利用す るために必要なコードが言語を問わず自動的に生成されます。

configuration_rtcb00_ja.png
RTCBuilderの設定画面

コンフィギュレーションパラメータを利用するためには、RTCBuilderのコンフィ ギュレーションタブを押し、パラメータリスト横のAddボタンを押します。す ると、コンフィギュレーションパラメータが一つ追加されますので、適切な

  • 名称 (必須)
  • データ型 (必須)
  • デフォルト値 (必須)

を入力します。

名称は(デフォルトではconf_name0等となっているので)、そのパラメータの性 質を端的に表す分かりやすい名前を付けてください。ドロップダウンリストか ら選択できる型名は、各言語において適切に変換され定義されます。Python等 明示的に型宣言が必要ない言語では、ここで設定された型名はコード上には現 れないかもしれません。

上でも述べたように、コンフィギュレーションパラメータは値を文字列として 与えて、文字列を特定の型に変換することで様々な型のパラメータに対応可能 です。ただし、外部から文字列として値が入力されるため、変換不可能な文字 列など不正なパラメータ入力があった場合。変換がエラーになる場合もありま す。ここで設定されたデフォルト値は、設定された値の変換が不正な場合に代 わりに使用される値です。

このほか、必須でない項目として以下の項目があります。必要に応じて入力し てください。

  • 変数名: 変数名として使用する文字列。空の場合は名称が使用されます。
  • 単位: このパラメータの単位。現在のところ、人間が読む以外には使われていません。
  • 制約条件: このパラメータの制約条件を与えます。この条件はRTSystemEditorで使用されます。連続値の場合は不等号、列挙値の場合はカンマ区切りなど指定できます。
  • Widget: RTSystemEditorでパラメータを操作するときに使用されるコントロール。text, slider, spin, radio から選択できます。
  • Step: 上記のWidgetがsliderやspinの場合のステップを指定します。

詳細については、画面右側のヒントや、RTCBuilderのマニュアルを参照してく ださい。

rtc-templateによる定義

rtc-template はコマンドラインから使用するコンポーネントテンプレートジェ ネレータです。rtc-templateでコンフィギュレーションを使用するには以下の ように指定します。

    /usr/local/bin/rtc-template -bcxx --module-name=ConfigSample 
    --module-type=DataFlowComponent 
    --module-desc=Configuration example component --module-version=1.0 
    --module-vendor=Noriaki Ando, AIST --module-category=example 
    --module-comp-type=DataFlowComponent --module-act-type=SPORADIC 
    --module-max-inst=10 --config=int_param0:int:0 
    --config=int_param1:int:1 --config=double_param0:double:0.11 
    --config=double_param1:double:9.9 
    --config=str_param0:std::string:hoge 
    --config=std_param:std::string:dara 
    --config=vector_param0:std::vector<double>:0.0,1.0,2.0,3.0,4.0
 
    # 実際には1行で入力するか、継続文字を行末に (UNIXでは \, Windowsでは ^) を補ってください

これは、サンプルに付属しているConfigSampleでの指定例です。

 --config=<名称>:<データ型>:<デフォルト値>

のように指定します。データ型については、その言語で使用するデータ型を指 定しますが、プリミティブ型以外ではうまく動作しなかったり、手動で修正が 必要な場合があります。

手動による定義

あまり推奨されませんが、手動でもコンフィギュレーションパラメータを定義 することができます。新たにパラメータを追加したくなった場合等に有効です が、ドキュメントやRTC.xmlファイル等を更新しないと、第三者がこのRTCを使 用した場合に仕様と実装の整合性が取れていないために、混乱を来たす可能性 がありますので注意してください。

ただし、コンフィギュレーションがどのように宣言され使用されるのかを知る ことは意味がありますのでここで説明します。

コンフィギュレーションを使用するには以下の手続きが必要です。

コンフィギュレーションパラメータ(以下パラメータ)の用途、名称、型を決める

上で述べたように、コンポーネントのどの部分でパラメータを使用するのか、 またそのパラメータの特徴を表す名称と実装時の型名(型のある言語の場合)を 決めます。

パラメータの変数をコンポーネントのヘッダ(private/protected)に宣言する

RTCBuilderやrtc-templateで生成したファイルであれば、以下のようなタグに 囲まれた部分がありますので、ここにコンフィギュレーションパラメータのた めの変数を宣言します。

  // Configuration variable declaration
  // <rtc-template block="config_declare">
 
  // </rtc-template>

上のConfigSampleの例であれば以下のようになります。

  // Configuration variable declaration
  // <rtc-template block="config_declare">
  int m_int_param0;
  int m_int_param1;
  double m_double_param0;
  double m_double_param1;
  std::string m_str_param0;
  std::string m_str_param1;
  std::vector<double> m_vector_param0;
  
  // </rtc-template>

コンポーネントの実装ファイルの static 変数 <コンポーネント名>_spec[] にパラメータの宣言とデフォルト値を追加する

コンフィギュレーションパラメータはコンポーネント内で、Propertiesというデータストアに入れられ管理されます。このProperties内では、

 conf.<コンフィギュレーションセット名>.<パラメータ名>

というキーでコンフィギュレーションパラメータを保持しています。デフォル ト値として default というコンフィギュレーションセット名が予約済みと なっており、デフォルト値はすべてこの default コンフィギュレーション セットとして定義されます。

上のConfigSampleの場合、以下のように追加します。

 // Module specification
 // <rtc-template block="module_spec">
 static const char* configsample_spec[] =
   {
     "implementation_id", "ConfigSample",
     "type_name",         "ConfigSample",
     "description",       "Configuration example component",
     "version",           "1.0",
     "vendor",            "Noriaki Ando, AIST",
     "category",          "example",
     "activity_type",     "DataFlowComponent",
     "max_instance",      "10",
     "language",          "C++",
     "lang_type",         "compile",
     // Configuration variables
     "conf.default.int_param0", "0",
     "conf.default.int_param1", "1",
     "conf.default.double_param0", "0.11",
     "conf.default.double_param1", "9.9",
     "conf.default.str_param0", "hoge",
     "conf.default.str_param1", "dara",
     "conf.default.vector_param0", "0.0,1.0,2.0,3.0,4.0",
  
     ""
   };
 // </rtc-template>

Configuration variables 以下の部分がデフォルトコンフィギュレーションセッ トの定義になります。

各変数を初期化子で初期化する

RTCBuilderやrtc-templateで生成された変数はコンストラクタの初期化子によ る初期化は行われませんが、可能であればすべての変数はコンストラクタの初 期化子で初期化したほうがよいでしょう。また、各変数にデフォルト値がセッ トされるのはonInitialize()関数の中の bindParameter() 関数が呼ばれた後で すので、原則としてそれ以前には使用してはいけません。

bindParameter()関数でパラメータと変数をバインドする

最後に変数とパラメータの名称、デフォルト値、さらに変換関数をバインドす ることで、単なる変数をコンフィギュレーションパラメータにします。 RTObjectクラスのメンバ関数(メソッド)であるbindParameter()を使用します。

 bindParameter(<パラメータ名称(文字列)>, 変数, <デフォルト値(文字列)>, <変換関数>)

上のConfigSample (C++の例) では以下のようになります。

  // <rtc-template block="bind_config">
  // Bind variables and configuration variable
  bindParameter("int_param0", m_int_param0, "0");
  bindParameter("int_param1", m_int_param1, "1");
  bindParameter("double_param0", m_double_param0, "0.11");
  bindParameter("double_param1", m_double_param1, "9.9");
  bindParameter("str_param0", m_str_param0, "hoge");
  bindParameter("str_param1", m_str_param1, "dara");
  bindParameter("vector_param0", m_vector_param0, "0.0,1.0,2.0,3.0,4.0");
  
  // </rtc-template>

こうすることで、各変数とコンフィギュレーションパラメータがバインドされ、 RTSystemEditor等からこれらの変数を操作することができる、コンフィギュレー ションパラメータが利用可能になります。

なお、bindParameter() に与える変換関数は、組込み型については、上記の例 のように不要で、特に明示的に与える必要はありません。しかし、独自の構造 体や複雑な型等をコンフィギュレーションパラメータとして使用したい場合は、 文字列からそれらの型への変換を定義しここに与える必要があります。変換関 数の詳細については後述します。

パラメータを使う

パラメータを使うのは非常に簡単です。これまで述べてきたように、コンフィ ギュレーションパラメータとして宣言された変数を単に利用するだけです。た だし、使用に当たってはいくつかの条件があり、これを守って利用する必要が あります。

変数が使用できるコールバック関数

コンフィギュレーション変数は、特定のコールバック関数 (onXXX()) 内でしか 利用することはできません。外部からのコンフィギュレーション変数の変更は 非同期的に行われます。通常このような場合には、ミューテックス等で変数へ の排他アクセス制御を行う必要がありますが、これを実現するにはコンポーネ ント開発者も各変数へのアクセス時にミューテックス保護を行う必要がありま す。これを回避するために、OpenRTM-aistでは外部からのコンフィギュレーショ ンの変更は、コールバック関数の外で行われるようになっています。

利用できるコールバック関数は、以下のものになります。

  • onInitialize() (※)
  • onActivated()
  • onExecute()
  • onStateUpdate()
  • onDeactivate()
  • onAborting()
  • onError()
  • onReset()
  • onFinalize() (※)

ほぼすべてのコールバック関数内でコンフィギュレーションパラメータを利用 することができます。ただし、onInitialize() においては、bindParameter() を行う前には当然コンフィギュレーションパラメータを利用できません。また、 onFinalize() 内では、その呼び出しの直前にコンフィギュレーションパラメー タに対してなされた変更が反映されない可能性があります。

変数は読み出し専用

コンフィギュレーションパラメータの変数は、コンポーネントの外部から変更 されその値がパラメータ用変数に代入されます。しかし、パラメータ用変数に onExecute()等内部の関数内で書きこんでも、外から見えるパラメータの値には 反映されません。

このように、変数の値の変更は一方通行ですので、コンポーネント内部からの 変数に対する書き込みは意味がありません。コンフィギュレーション変数は read only で使いましょう。

値が正しいか常にチェックする

コンフィギュレーションパラメータの値は、上述したように外部から文字列と して与えられたものを変換関数で変換したものが実際使用される変数に代入さ れます。文字列ですので、本来数値が代入されるべきところに文字列が代入さ れたり、short int で宣言された変数に、上限以上の大きさの数値が代入される こともあり得ます。従って、受け取った側では変数が想定されている値の範囲 内に入っているか、あり得ない値が代入されていないかについて、プログラム 上で使用前には常にチェックすることが推奨されます。

パラメータを設定する

コンフィギュレーションパラメータは、いくつかのセットを持ち、実行時にそ れらを同時に変更できることを上で述べました。その一方で、RTCBuilderや rtc-templateでコンポーネントを設計する時点では、デフォルトコンフィギュ レーションセットしか定義できませんでした。ここでは、コンフィギュレーショ ンセットの使い方について説明します。

コンポーネント設定ファイル

デフォルトコンフィギュレーションセットはソースコードに埋め込まれます。 同じ方法で、他のコンフィギュレーションセットも原理的にはソースコードに 埋め込むことで増やすことができます。しかし、RTCコンフィギュレーション機 能の目的は、ソースコードを変更しないで、用途に応じてパラメータを変更す ることで、一つのコンポーネントを様々な用途に使うことでしたので、ソース コードに他のコンフィギュレーションセットを埋め込むのは本末転倒です。

コンフィギュレーションセットはコンポーネントのコンフィギュレーションファ イルで与えることができます。コンポーネントの設定を行うファイルには rtc.confがありますが、これは主にコンポーネントを管理するミドルウエアの ための設定ファイルで、コンポーネントのための設定ファイルは、rtc.conf内 で以下のように指定することができます。

 corba.nameservers: localhost
 naming.formats: %h.host_cxt/%n.rtc
 example.ConfigSample.config_file: configsample.conf

example.ConfigSample.config_file の部分がコンポーネントのコンフィギュレー ションファイルの指定部分です。コンフィギュレーションファイルを指定する 部分は以下のようになっています。

 <カテゴリ名>.<モジュール名>.config_file: <ファイル名>

また、コンポーネントのモジュール名の代わりにインスタンス名を与えること もできます。

 <カテゴリ名>.<インスタンス名>.config_file: <ファイル名>

したがって、インスタンス毎に異なるコンフィギュレーションファイルを与え ることもできます。

 example.ConfigSample0.config_file: consout0.conf
 example.ConfigSample1.config_file: consout1.conf
 example.ConfigSample2.config_file: consout2.conf

コンフィギュレーションセットの設定

コンフィギュレーションファイルの中には、使用したいコンフィギュレーショ ンセットを記述します。

 configuration.active_config: mode1
 
 conf.mode0.int_param0: 12345
 conf.mode0.int_param1: 98765
 conf.mode0.double_param0: 3.141592653589793238462643383279
 conf.mode0.double_param1: 2.718281828459045235360287471352
 conf.mode0.str_param0: mode0
 conf.mode0.str_param1: foo
 conf.mode0.vector_param0: 0.0,0.1,0.2,0.3,0.4
 
 conf.mode1.int_param0: -999
 conf.mode1.int_param1: 999
 conf.mode1.double_param0: 297992458
 conf.mode1.double_param1: 2.97992458e+8
 conf.mode1.str_param0: mode1
 conf.mode1.str_param1: AIST
 conf.mode1.vector_param0: 1,2,3,4,5,6,7,8,9
 
 conf.__widget__.int_param0: slider.1
 conf.__widget__.int_param1: spin
 conf.__widget__.double_param0: slider.0.1
 conf.__widget__.double_param1: text
 conf.__widget__.str_param0: radio
 conf.__widget__.str_param1: text
 conf.__widget__.vector_param0: text
 
 conf.__constraints__.int_param0: 0<=x<=150
 conf.__constraints__.int_param1: 0<=x<=1000
 conf.__constraints__.double_param0: 0<=x<=100
 conf.__constraints__.double_param1: 
 conf.__constraints__.str_param0: (default,mode0,mode1,foo,bar,radio)
 conf.__constraints__.str_param1: 
 conf.__constraints__.vector_param0: 

アクティブコンフィギュレーションセットの指定

最初の行の configuration.active_config で、アクティブなコンフィギュレー ションセット名を指定しています。ここではmode1というセット名で、当然、存 在するセット名を指定する必要があります。

 configuration.active_config: mode1

コンフィギュレーションセットの設定

次に、conf.mode0 で始まるパラメータのリストがありますが、これがセット名 mode0 のコンフィギュレーションパラメータのリストです。指定の仕方は、 ソースコードとほぼ同じように

 conf.<セット名>.<パラメータ名>: <デフォルト値>

となっています。必ず、存在するすべてのコンフィギュレーションパラメータ について指定してください。指定がない場合はデフォルト値が使用されます。 その次に、conf.mode1で始まるパラメータのリストがありますが、これも mode0同様、mode1というセット名のパラメータの設定です。

拡張機能

次に、conf, _ _widget_ _で始まる設定リストがあります。これは、 RTSystemEditorで使用される特殊なパラメータです。RTCBuilderでコンフィギュ レーションパラメータを設定するときwidgetを指定できることを上で説明しま したが、ここで設定された内容が、conf._ _widget_ _に設定されます。 slider, radio, spin, text の4種類を設定することができ、それぞれ RTSystemEditorでコンフィギュレーションパラメータ設定ダイアログを開いた ときに、スライダ、ラジオボタン、スピンボタン、テキストボックスでパラメー タを操作することができます。

 conf.__widget__.<パラメータ名>: ウィジェット名

なお、スライダー (slider) を設定した場合、

 conf.__widget__.int_param0: slider.5

のようにすることで、スライダーの刻み幅を5にすることができます。現在のと ころ、この刻み幅を小数にすることはできません。ただし、今後のバージョン アップで改善される可能性があります。また、スピンボタンはその性質上常に 1刻みです。int等整数値のパラメータにのみ使用することをお勧めします。

これら conf._ _widget_ _ パラメータを設定した場合、その下の conf._ _constraints_ _ パラメータを設定する必要があります。 conf._ _constraints_ _ パラメータは、値の範囲を設定するための特殊なパラメー タで、指定の仕方には、スライダやスピンボタンのための、仮変数 x と等 号、不等号を用いた以下のような指定の仕方や、

 conf.__constraints__.int_param0: 0<=x<=150

radioボタンによる括弧とカンマによりリストによる以下のような指定の方法が あります。

 conf.__constraints__.str_param0: (default,mode0,mode1,foo,bar,radio)

このほかにも、conf._ _constraints_ _ パラメータには制約の記述方法がありま すが、ウィジェットに利用される制約条件の指定方法は現在のところ上記の2つ だけです。

変換関数について

C++等では、intやdoubleなどの組込み型については特に変換関数を指定する必 要はありません。一方で、構造体やSTLコンテナなどユーザ独自の型を利用した い場合もあります。この場合、文字列からそれぞれの型への変換をどのように するかをbindParameter()に関数として与えてあげる必要があります。

変換関数については以下のように、各言語ごとにルールがあります。以下、各 言語ごとの方法を述べます。

C++の場合の変換関数

C++におおいては、bindParameterのプロトタイプ宣言は

 template <typename VarType>
     bool bindParameter(const char* param_name, VarType& var,
                const char* def_val,
                 bool (*trans)(VarType&, const char*) = coil::stringTo)
               

のようになっており、第4引数の trans に適当な関数ポインタを与えることで、 文字列から当該型への変換が行われます。デフォルトでは、coilライブラリ関 数の stringTo() 関数が与えられています。自分でこのstringTo()に相当する 変換関数を書いて、関数ポインタを与えることもできますが、 coil::stringTo()関数自体も関数テンプレートとなっており、std::streamに対 するoperator>>()関数

 std::istream& operator>>(std::istream&, T)

が定義されていれば、自動的にこれを利用して文字列から特定の型への変換が 行われます。

すなわち、std::cin >> <ある型の変数> のような書き方ができるのであれば、 その型はoperator>>()が定義されており、特に変換関数を書かなくともコンフィ ギュレーションのパラメータとして利用することができます。

もし、変換関数がない場合、例えば、以下のようにカンマ区切りの数値列

 0.0,1.0,2.0,3.0,4.0

を std::vector<double> へ変換するための変換関数は、

 #include <istream>
 #include <ostream>
 #include <vector>
 #include <string>
 #include <coil/stringutil.h>
 
 template<typename T>
 std::istream& operator>>(std::istream& is, std::vector<T>& v)
 {
   std::string s;
   std::vector<std::string> sv;
   is >> s;
   sv = coil::split(s ,",");
   v.resize(sv.size());
   for (int i(0), len(sv.size()); i < len; ++i)
     {
       T tv;
       if (coil::stringTo(tv, sv[i].c_str()))
         {
           v[i] = tv;
         }
     }
   return is;
 }

このように実装することができます。なお、これは OpenRTM-aist C++版のサン プル、ConfigSample コンポーネントのソースに含まれる VectorConvert.h で す。

これを、bindParameter() が呼ばれるソース (例えば、ConfigSampleコンポー ネントであれば ConfigSample.cpp)、通常はコンポーネントの実装ソースで includeしてあげれば、コンパイル時にコンパイラが判断して適当な変換関数が 利用されます。

Javaの場合の変換関数

Javaの場合は、変換関数というものを別途与えるのではなく、コンフィギュレー ション変数のホルダクラスにおいて定義される stringFrom() メソッドに文字 列から実際の型への変換を記述します。

以下に、OpenRTM-aist Java版のConfigSampoleで定義されている、カンマ区切 り数値列をVector型に変換するための変換関数を示します。

 package RTMExamples.ConfigSample;
 
 import java.io.Serializable;
 import java.util.Vector;
 
 import jp.go.aist.rtm.RTC.util.ValueHolder;
 
 public class VectorHolder  implements ValueHolder, Serializable {
 
     /**
      * Vector型データ設定値
      */
     public Vector value = null;
 
     /**
      * デフォルトコンストラクタ
      *
      */
     public VectorHolder() {
     }
 
     /**
      * コンストラクタ
      *
      * @param initialValue 初期値
      *
      */
     public VectorHolder(Vector initialValue) {
         value = new Vector(initialValue);
     }
 
     /**
      * 文字列からVector型に変換して設定
      *
      * @param def_val 設定値文字列表現
      *
      */
     public void stringFrom(String def_val) throws Exception {
         value = new Vector();
         String values[] = def_val.split(",");
         for( int intIdx=0;intIdx<values.length;intIdx++ ) {
             value.add(values[intIdx]);
         }
     }
     /**
      * 設定値の取得
      *
     * @return 設定値
      *
      */
     public Vector getValue(){
         return value;
     }
     /**
      * 設定値を文字列に変換
      *
     * @return 変換文字列
      *
      */
     public String toString(){
         StringBuffer retVal = new StringBuffer();
         while(value.iterator().hasNext()) {
             retVal.append(value.iterator().next());
             if(value.iterator().hasNext()) retVal.append("'");
         }
         return retVal.toString();
     }
 }

Pythonの場合の変換関数

Python版OpenRTM-aistでは、デフォルトでは基本型とそのリストに対応してお り、それ以外の変換が必要なら、bool stringTo(type, string) であるような 関数を定義して、bindParameter() の第4引数に関数オブジェクトを渡します。

何をパラメータにするか?

RTコンポーネントを作成するうえで、何をコンフィギュレーションパラメータ にすればよいのか考えてみましょう。

あるパラメータがあり、これを外部から変更するにはいくつかの方法が考えら れます。データポートを利用して変更する方法、サービスポートを利用して変 更する方法、そしてコンフィギュレーションを利用して変更する方法です。

コンフィギュレーション機能はコンポーネント内部のパラメータを変更するた めの機能です。したがって、ロジック内のパラメータはコンフィギュレーショ ンパラメータとして外部から変更できるようにするべきです。しかし、ある変 量をコンフィギュレーションパラメータにすべきなのかそうでないのか迷うケー スもあると思います。ここではそういったケースについて少し考えてみます。

更新頻度

コンフィギュレーションパラメータは、通常はシステムが動き出す前に1度だけ、 あるいは設定変更が必要になった場合にだけ、外部からパラメータを与えるた めに利用します。更新頻度がシステムのライフサイクル上で1回ないしは数回程 度であれば、コンフィギュレーションを使うのがよいでしょう。

また、上でも述べましたが、コンフィギュレーションはツールやアプリケーショ ンからは文字列として与えられ、コンポーネント内でそれぞれの型に変換しま す。変換にはある程度(最近のPCでは数usから数百us程度ですが)時間がかかり ますので、例えば1ms周期でデータを送る用途には向きません。ではそのくらい の頻度でパラメータを変更できるのでしょうか?実際に使用する際には、パラ メータの数やコンピュータ、ネットワークの速度にも依存しますが、数百msま たはそれ以上の頻度では事実上問題なくパラメータを変更できます。ただし、 そのように周期的に何度も値を変更する必要があるものはデータポートを使う べきでしょう。

更新のタイミング

コンフィギュレーションパラメータはRTSystemEditorやRTShellなどのツールから、いつでも更新することができます。 しかし、実際に変更されたパラメータは onExecute や onActivated などの関数で使用する関数内で参照される前にあるタイミングで実際の変数に反映されます。更新のタイミングは以下の通りです。

初期化時 onInitialize() の直後
アクティブ化時 onActivated() が呼ばれる直前
エラー時 onError() の直後
アクティブ状態 onStateUpdate() の直後 ≒ onExecute の後、次のonExecute() の直前

データかパラメータか?

例えば、遠隔地のセンサから定期的にデータを中央のサーバに送るシステムを 考えます。データは1時間に1回だけ送られ、サーバ側ではそれをログに記録す るとします。このとき、このデータはデータポートを使って送るべきでしょう か?それとも、サービスポートを使うべきか、あるいはコンフィギュレーショ ンを使うべきなのでしょうか?

送られるものはセンサのデータですので、データポートを利用して送るの が最も適しているといえます。コンフィギュレーションは外部からパラメータ を設定するための仕組みですので、たとえ更新頻度が1時間に一回であって も、このデータをコンフィギュレーションでコンポーネントに伝達するのは不 適切といえます。ただし、データポートでは実現できなクライアントとサーバ 側の複雑なやり取り(トランザクション等)を実現したい場合は、サービスポー トが使われるかもしれません。

サービスかパラメータか?

データポートにすべきか、コンフィギュレーションにすべきかは、実際にはあ まり迷うことはないでしょう。一方で、RTCロジック内のパラメータをサービス ポートから変更するべきか、コンフィギュレーションパラメータにすべきか迷 う場面は多いと思います。

コンポーネントがある種の典型的かつある程度まとまった機能を提供する場合、 その機能はサービスポートのインターフェースによって外部に提供されます。 サービスインターフェースでは、対象の状態を取得したり、設定・モード・パ ラメータを変更したりするためのオペレーションを提供します。状態の取得は 別として、設定を行ったり、モード・パラメータを変更したりする機能はコン フィギュレーションと大変似ています。

結局のところはどちらで設定しても大差ないのですが、対象とするRTCの機能が すでにサービスインターフェースとして定義されていたり、状態の取得と設定 が必要になるなどある程度複雑な機能をて供する場合、サービスインターフェー スを介した操作が適していると言えるでしょう。それ以外の簡単なパラメータ・ モード等の設定にはコンフィギュレーションを利用するとよいでしょう。

まとめ

この説では、コンフィギュレーション機能について定義の仕方や使い方につい て説明しました。ロジック内のパラメータはコンポーネントの再利用性を向上 させるために、できるだけこの機能を利用して外部化するべきです。何をコン フィギュレーションパラメータにすべきか、すべきでないかといったことにつ いても注意を払う必要があります。コンフィギュレーション機能を有効に利用 すれば、作成するコンポーネントも再利用性の高いものになるでしょう。

最新バージョン

初めての方へ

Windows msi(インストーラ) パッケージ (サンプルの実行ができます。)

C++,Python,Java,
Toolsを含む
1.1.2-RELEASE

RTコンポーネントを開発するためには開発環境のインストールが必要です。詳細はダウンロードページ

統計

Webサイト統計
ユーザ数:1604
プロジェクト統計
RTコンポーネント286
RTミドルウエア21
ツール20
文書・仕様書1

OpenHRP3

動力学シミュレータ

Choreonoid

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

OpenHRI

対話制御コンポーネント群

OpenRTP

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

産総研RTC集

産総研が提供するRTC集

TORK

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

DAQ-Middleware

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

VirCA

遠隔空間同士を接続し、実験を行うことが可能な仮想空間プラットホーム