Help us understand the problem. What is going on with this article?

OpenRTM初心者が注意すべきこと(C++)

More than 1 year has passed since last update.

プロジェクトが炎上したので反省文的な備忘録

※2017/10/16 いくつか思い出したやらかしに関して追記
        

反省点一覧

RTCの設定変更はRTC Builderから行う

 コンフィギュレーション等の変更時、依存関係も含め全てのファイルを更新してくれます。
 間違っても手動で変更しないようにしましょう。後々めんどくさいことになります。
 【参考URL】 http://ysuga.net/?p=58

Screenshot from 2017-10-13 22-30-46.png
 ※RTC Builderを使えば、コンフィギュレーションの追加等の変更部分のみMerge可能。

ユーザ名に気を付ける

 RTC Builder を使用してサービスポートを作成する際、使用するIDLファイルのフルパスが
 RTC.xml 内に記載されます。個人で作成する分には問題ありませんが、客先に納品する際には
 十分注意しましょう(自社名・個人名を出してはいけないとき等)。

RTCタグ内に処理を書かない

 RTC BuilderでのMerge時にタグ内の処理が上書きされます。
 自分がやらかしたのは、サービスポート用のインクルードが記載されている場所に
 任意のインクルードを書いたため、Merge時に全削除されました。

  // Service Consumer stub headers
  // <rtc-template block="consumer_stub_h">
  #include "BasicDataTypeStub.h"
  #include <iostream>              ← Merge時に消える
  // </rtc-template>

 

設定ファイルはバイナリと同ディレクトリでないと読み込まれない

 設定ファイルとして【RTC名】.conf、rtc.conf がありますが、
 これはRTCの実行バイナリ(コンパイル直後だと【RTC名】/build/src)と
 同ディレクトリでなければ読み込まれません。デフォルトでは【RTC名】ディレクトリ直下に設置されているので、
 実行バイナリと同ディレクトリにコピーして使いましょう。
 【参考URL】 http://www.openrtm.org/openrtm/ja/content/コンフィギュレーション-基礎編

 ※2017/10/16 追記
 設定ファイルはオプションによってパス指定可能とのことです。

  $ ConsoleInComp -f ../conf/hoge.conf

 @n-andoさん、情報提供ありがとうございます!

onExecute()内でロジックを書かない

 これはRTMに限った話ではないですが、onExeucute()内でメインロジックを書かないようにしましょう。
 コードの保守性や可読性が下がります。別クラスや別メソッドに切り分けてください。
 【参考URL】 http://ysuga.net/?p=56   ※最下部に同様の内容が記載されている。
       http://ysuga.net/?p=415   ※具体的に記載してあって分かりやすい。

コンフィギュレーション値を必要とするインスタンスはonActivated()以降で作成する

 設定ファイル(【RTC名】.conf)内記載のコンフィギュレーション値が反映されるのはonInitialized()直後です。
 当初、コンフィギュレーション値を必要とするインスタンスを
 onInitialize()内で作成していましたが、コンフィギュレーションの変更が反映されないという問題が発生しました。
 onInitialize()内ではデフォルト値とコンフィギュレーション変数とのバインドを行っているに過ぎません。
 コンフィギュレーションによって動的に変更する可能性があるものはonActivated()以降に確保しましょう。
 【参考URL】 http://www.openrtm.org/openrtm/ja/content/コンフィギュレーション-基礎編 

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

グローバル変数は使用しない

 OpenRTMはマルチスレッドモデルであるため、複数のRTC間でメモリ領域を共有するようです。
 そのため、異なるRTCで定義されたグローバル変数が使用できてしまいます。グローバル変数はスコープ的にも使用しないに越したことはないので、
 問題なければメンバ変数に格納してしまいましょう。グローバル変数をメンバ変数に格納したからといって、
 実装に困るようなことはないはずです。
 【参考URL】 http://ysuga.net/?p=415

列挙型は必ず初期化して送信する

 OpenRTMというよりCORBAの仕様だと思いますが、列挙型を初期化せずに送信しようとすると、マーシャリングエラーを起こしてRTCが落ちます。
 おそらく、ゴミか何かが入った状態の列挙型変数をマーシャリングしようとしているので、
 上手く対応付けできずに落ちているのかと思います。
 列挙型は必ず初期化してから送信してください。
 ※確実な情報が得られなかったため、詳しく知ってる方いたら教えてください。

サービスポートが未接続・inactiveの状態を考慮する

 サービスポートが未接続・inactive時に、RTCは例外を送出します。
 回避方法は公式のチュートリアルに載っていますので参考にしてください。
 【参考URL】 http://www.openrtm.org/openrtm/ja/content/windowsでの動作確認-0

  // サービスポートが接続している、かつ、接続先がinactiveでない
  if (!CORBA::is_nil(m_MyService._ptr()) && !m_MyService->_non_existent() )
  {
      // サービスポートによる処理
  }
  else
  {
      // ログ出力
  }

 RTC単体で動作させた時にも問題ないようコーディングしろってことですね。 
 ちなみに、データポートは未接続とかinactive状態でも例外を送出しません。
 データが送信できたかどうかの確認は可能なようです。
 【参考URL】 http://www.openrtm.org/openrtm/ja/content/データポート-基礎編

  RTC::ReturnCode_t ConsoleIn::onExecute(RTC::UniqueId ec_id)
  {
    std::cout << "Please input number: ";
    std::cin >> m_out.data;
    if (!m_outOut.write())
      {
        DataPortStatusList stat = m_outOut.getStatusList();
        for (size_t i(0), len(stat.size()); i < len; ++i)
          {
            if (stat[i] != PORT_OK)
              {
                std::cout << "Error in connector number " << i << std::endl;
              }
          }
      }
    return RTC::RTC_OK;
  }

最後に

公式のチュートリアルを読んでください。
【参考URL】 http://www.openrtm.org/openrtm/ja/content/rtcプログラミング入門-0

サンプルのみを作成しているサイト等で、作り方のみを確認すると詳細な仕様が
分からなくなってしまうので、確実にチュートリアルを読みましょう。
プログラム作成後に突っ込みどころ満載だと迷惑を掛けます(自分のこと)。

個人的には公式のチュートリアルと下記サイトがおすすめです
【参考URL】 http://ysuga.net/?cat=17

おまけ

なんだかんだ言って、OpenRTM開発で一番お世話になったのはQtCreatorです。
【参考URL】 http://qt.io/download-open-source/
CMakeLists.txt読み込むだけでプロジェクト作成してくれるのは素晴らしいです。
当初VSCode使ってましたがつらすぎました。
これ以外に何かOpenRTM開発に最適なIDEがあったら教えてください。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away