RTミドルウェアに基づく視覚トラッキングによるクァッドロータの誘導 ~ サービスポートと共有メモリによる画像の送受信

RTミドルウェアに基づく視覚トラッキングによるクァッドロータの誘導 ~ サービスポートと共有メモリによる画像の送受信

Author: 
sasaki.akinori

本ページは作成途中です.

概要

本ページはRTMコンテスト2011にて発表予定のRTコンポーネントのページです.視覚トラッキングによるクァッドロータの誘導を目的として開発中のRTコンポーネント群を公開します.ビジョンシステムは複数のカメラにより構成し,映像を複数のRTコンポーネントにより処理します.RTコンポーネント間の画像の受け渡しをデータポートにより行うと遅延が顕著となる問題に対し,処理速度を改善する目的で共有メモリを使用して画像の受け渡しを 行います。

共有メモリを使用して画像の受け渡しを行うには、RTコンポーネント間で共有メモリセグメントおよびそのセグメント上の画像の識別名を 受信側のRTコンポーネントが知る必要があります。これにはサービスポートを利用して、送信側から受信側に識別名を通知します。

ライセンス

修正BSDライセンス(三条項)

ビルドに必要なライブラリ

動作テスト環境

  • Ubuntu 11.04 (カーネル 2.6.38-11-generic)
    • gcc 4.5.2
    • OpenRTM-aist 1.1.0-RC2
    • rtctree 3.0.0
    • rtshell 3.0.0
    • OpenCV 2.3.1
    • Boost 1.43
    • USBカメラ Logicool C910 。ドライバは uvcvideo。ただしパッチ(12)を適用し、insmodのときに次のようにパラメータを指定する。
       sudo insmod uvcvideo.ko quirks=128

ビルド手順

各RTCおよび関連するソースファイルをビルドするMakefileを用意しています。次のコマンドで全てのビルドが行われます。
 $ make

使用テスト例

RTCの起動およびRTC間の接続を行うBashシェルスクリプトを用意しています。 接続後に各RTCをactivateするにはRTSystemEditor または rtshell を使用します。

  • カメラからの画像読み込み、表示、一時保存のテスト
     $ ./loadHoldTest.sh
  • 背景差分のテスト
     $ ./loadBgSubTest.sh
  • 重心抽出のテスト
     $ ./loadCoMExtTest.sh

共有メモリによる画像の送受信

送信側(Provider)の処理

宣言

画像を送信する側のRTCのクラス宣言は次のように書きます。

 1 class ShmCvProvider : public RTC::DataFlowComponentBase
 2 {
 3   // ...省略...
 4   ShmMat* m_shmImgOut; 
 5   RTC::CorbaPort m_shmMatServicePortOut;
 6   ShmMatServiceInterfaceSVC_impl m_shmMatServiceOut;
 7   // ...省略...
 8 };

第4行にある ShmMat は OpenCVのcv::Mat 1個に対応するクラスで,共有メモリに そのインスタンスを作ります。第5行の m_shmMatServicePortOut は画像の識別名を 通知するための出力側サービスポート,第6行の m_shmMatServiceOut は識別名通知 サービスのインタフェースを実装したクラスのインスタンスです。 画像を送信するために,RTCの状態遷移に応じて,以下のような処理を行います。

準備 onInitialize()

まずonInitialize()においては次のようにして画像を送信する準備をします。

  1 RTC::ReturnCode_t ShmCvProvider::onInitialize()
  2 {
  3   // ..省略...
  4   m_shmMatServiceOut.setShmSegmentName(ShmMatAllocator::instance()->segmentName());
  5   m_shmImgOut = ShmMatAllocator::instance()->createShmMat();
  6   m_shmMatServiceOut.addShmMatName(m_shmImgOut->name());
  7   m_shmMatServicePortOut.registerProvider("ShmMatService",
  8                                           "ShmMatServiceInterface",
  9                                           m_shmMatServiceOut);
 10   addPort(m_shmMatServicePortOut);
 11   // ..省略...
 12 }

第4行は共有メモリ領域の識別名を設定する処理です。ShmMatAllocatorは共有メモリ領域の管理を 担当するクラスであり,一つのRTC(プロセス)につき,インスタンスを一つのみ持ちます (いわゆる Singleton です)。そのインスタンスへのポインタはShmMatAllocator::instance() によって取得できます。メンバ関数 segmentName()は共有メモリ領域について自動生成された識別名を 返します。識別名はUUID(Universally Unique Identifier)により構成されており,自動生成される 識別名はインスタンスごとに異なります(UUIDの生成にはBoost.Uuidライブラリを利用しています)。

第5行ではメンバ関数createShmMat()により共有メモリ上に ShmMatのインスタンスを作成し, これへのポインタを m_shmImgOutに代入しています。

第6行では自動生成されたShmMatの識別名を送信画像の識別名リストに追加しています。ShmMatの識別名 も共有メモリ領域の識別名と同様にUUIDで構成されており,インスタンスごとに異なる識別名が 自動生成されます。

第7行はサービスポートm_shmMatServicePortOutに実際にサービスを提供するインスタンス m_shmMatServiceOutを指定しています。

第10行はRTCにサービスポートを追加登録しています。これによりサービスポートm_shmMatServicePortOutが 他のRTCのサービスポートと接続できる状態になります。

画像処理結果の送信 onExecute()

onExecute()においては次のような処理を行います。

  1 RTC::ReturnCode_t ShmCvProvider::onExecute(RTC::UniqueId ec_id)
  2 {
  3   // ..省略...
  4   m_shmImgOut->lock();
  5   *m_shmImgOut = doSomething(m_tmpImg);
  6   m_shmImgOut->unlock();
  7   // ..省略...
  8 }

第4行は ShmMatのインスタンスを他のRTC(プロセス)から同時にアクセスされない状態に 設定しています。実装上はBoost.Interprocessライブラリのmutex(mutual exclusion; 相互排他) オブジェクトを利用しています。

第5行では何らかの画像処理(doSomthing())により得られた cv::Mat 形式 の画像データを m_shmImgOut が管理する共有メモリ上 にコピーしています。ここで使用している演算子"="は ShmMatによりオーバロードされています。

第6行ではメンバ関数lock()と反対に,ShmMatのインスタンスを他のRTC(プロセス)から アクセスできる状態に設定しています。

共有メモリ上の画像データの解放

RTCの実行を停止する際などに画像データを共有メモリから解放するには 次のような処理を行います。

  1  RTC::ReturnCode_t ShmCvProvider::onShutdown(RTC::UniqueId ec_id)
  2  {
  3    // ...省略...  
  4    m_shmMatServiceOut.deleteShmMatName(m_shmImgOut->name());
  5    ShmMatAllocator::instance()->releaseShmMat(m_shmImgOut);
  6    // ...省略...  
  7  }

第3行では送信画像の識別名リストから m_shmImgOutの識別名を削除しています。 第4行ではShmMatのインスタンスを共有メモリから解放しています。

受信側(Consumer)の処理

宣言

画像を受信するRTCは次のように宣言します。

 1  class ShmCvConsumer : public RTC::DataFlowComponentBase
 2  {
 3    // ...省略...
 4    ShmMat* m_shmImgIn; 
 5    RTC::CorbaPort m_shmMatServicePortIn;
 6    ShmMatFinder m_shmMatFinder;
 7 // ...省略...
 8 };

第4行の m_shmImgIn は共有メモリ上の画像データShmMatのインスタンスへのポインタ変数です。 この m_shmImgIn に設定すべき ポインタ値を取得するには第5行のサービスポート m_shmMatServicePortIn および 第6行の m_shmMatFinder を使います。 ShmMatFinder は サービスポートから得られる識別名を基に ShmMatを共有メモリから見つけ出し,これへの ポインタを取得します。

準備

onInitialize() において,以下のように画像を受信する準備をします。

 1 RTC::ReturnCode_t ShmCvConsumer::onInitialize()
 2 {
 3   // ...省略...
 4   m_shmMatFinder.getRegistered(m_shmMatServicePortIn);
 5   addPort(m_shmMatServicePortIn);
 6   // ...省略...
 7 }

第4行ではサービスポート m_shmMatServicePortInにサービスのconsumerであるインスタンス を登録しています。

第5行ではサービスポート m_shmMatServicePortIn をこのRTCに登録しています。 これにより サービスポート m_shmMatServicePortIn が他のRTCと接続できる状態になります。

画像処理

共有メモリにある画像にアクセスするには次のように処理を行います。

  1 RTC::ReturnCode_t ShmCvConsumer::onExecute(RTC::UniqueId ec_id)
  2 {
  3   // ...省略...
  4   const int MAT_ID = 0;
  5   if(ShmCvUtil::checkShmMatReady(m_shmMatFinder, m_shmImgIn, MAT_ID)){
  6     m_shmImgIn->lock();
  7     doSomething((*m_shmImgIn)(), m_tmpImg);
  8     m_shmImgIn->unlock();
  9   }
 10   // ..省略...
 11 }

第4行は画像の識別番号を定数として定義しています。ShmMatAllocator::createShmMat() により作成された ShmMat は,ShmMatServiceInterfaceSVC_impl::addShmMatName()で 送信対象として登録したときに0から始まる番号が割り当てられます。したがって画像を 1枚ずつ送受信する状況で扱う画像の識別番号は0です。

第5行のShmCvUtil::checkShmMatReady() は識別番号MAT_ID および m_shmMatFinder を用いて, サービスポート経由で MAT_ID に対応する識別名(UUID)を問い合わせ,これに対応する 共有メモリ上のShmMatを見つけ出し,m_shmImgIn にそのポインタを設定します。 画像共有の準備が完了しており,m_shmImgIn に NULL でないポインタ値が設定されたとき ShmCvUtil::checkShmMatReady() は true を返し,そうでないときは false を返します。

第6行は ShmMatのインスタンスを他のRTC(プロセス)から同時にアクセスされない状態に 設定しています。これは送信側で行う処理と同じです。

第7行は受信した画像に対して何らかの処理(doSomething())を行うことを示しています。 ここで使用している演算子"()"はオーバロードされており,ShmMatが管理しているcv::Matへの const参照を返します。したがってdoSomething()は,cvtColor()などのOpenCVの関数で そのまま置き換えることができます。

第8行ではメンバ関数lock()と反対に,ShmMatのインスタンスを他のRTC(プロセス)から アクセスできる状態に設定しています。

停止

RTCの実行を停止する際などに共有メモリ上の画像へのアクセスを停止するには 次のように処理を行います。

 1 RTC::ReturnCode_t ShmCvConsumer::onDeactivated(RTC::UniqueId ec_id)
 2 {
 3   // ...省略...
 4   m_shmMatFinder.close();
 5   m_shmImgIn = NULL;
 6   // ...省略...
 7 }

第4行は共有メモリ領域の使用を停止する処理です。再度ShmMatFinder::open() を 使わない限り,共有メモリ領域へのアクセスはできなくなります。共有メモリ上の データは解放されず,そのまま残っています。

第5行では 共有メモリ領域が無効になり,m_shmImgIn のポインタも無効になったので 誤って使うことがないように NULL を設定しています。

問合先(メールアドレス): 
sasaki.akinori<at>iri-tokyo.jp
Resources
Project Information
OS: 
Linux
言語: 
C++
OpenRTM ver.: 
1.1
Average: 
5
Average: 5 (1 vote)
Last modified: 
Thu, 2011-12-29 02:12

latest Releases

For Begginers

Windows msi(installer) package (only trying samples)

Development environment is required for RT-Component development. See download page for details.

Number of Projects

Join our slack

Enter email address for slack invite.

OpenHRP3

Dynamics simulator

OpenHRI

Human-Robot-Interaction RTCs

OpenRTP

Integrated Development Platform

OpenINVENT

Mobile Robot RTCs