[openrtm-users 00402] Re: リングバッファからのデータ取得につきまして

kurihara shinji shinji.kurihara @ aist.go.jp
2008年 3月 27日 (木) 23:38:38 JST


産総研 中島様

産総研タスクグループ 栗原です。

> [dataOutComp]が急にサイクルが早くなり、データを2度書き終えてしまった可能
> 性もありますが、これは考えにくいため、
> [dataOutComp]側がバッファへのデータ書き込みに失敗していると考えているの
> ですが、”ロック”がかかる状況が発生したのでしょうか?
dataOutCompの方が実行サイクルが早く、dataInComp側でread()から次回のread()ま
でにdataOutCompがwrite()を2回行う事がない事が保証されている場合は別ですが、
もし保証されていない(なんらかの原因で2回write()が行われる可能性がある)場合、
OpenRTM-aist-0.4.1のRingBufferの実装では、1回目のwrite()で書き込まれたデー
タは2回目のwirte()以降read()する事ができません。
ですので、データが欠落する事となります。

問題の切り分けのために、dataInComp側にOnWriteコールバックオブジェクトを実装
し、OnWriteオブジェクトの中でもタイムスタンプデータをファイル等に出力し、
read()で得られるデータと比較する事でread()-read()間にwrite()が複数回行われ
たかどうかを判定する事ができますので、お試し頂ければと思います。
なお、コールバックオブジェクトの実装方法は、OpenRTMオフィシャルサイトのマニ
ュアル > RTコンポーネント作成 > データポートのあるコンポーネント > ConsoleOut
の実装 > コールバックオブジェクト に記述されております。

また、質問内容にあります"ロックがかかる状況"に関してですが、OutPortのwrite()
からInPortのread()までの間にOpenRTMでは相互排除のロック機構は実装されており
ません。

以上、宣しくお願い致します。



> 安藤様
> 
> 産総研の中島です。
> 
> 2つのRTC間でデータポートでのデータ送受信を行う際に、
> 以下に示しますようにデータ取得にて欠落が発生するため、
> 原因or対処法についてご教示願います。
> 
> 
> <現象>
>   [dataOutComp][dataInComp]の2つコンポーネントがあり、データポートにて
> TimedDoubleSeqのデータを[dataOutComp]-->[dataInComp]方向に送信しており、
> 実行サイクルは「dataInComp」の方が早いため、何回かonExecuteがループして
> から「dataOutComp」よりデータを取得できているのですが、稀に、データを取
> 得していない状態が発生します。(以下のサンプルソースとデバッグ参照)
> 
>   データの取得は、まず、isNew()でバッファに新たなデータが入っていないか
> 確認し、なければ今回のonExecuteは何も処理せず、データがあればそれをread()
> しています。
> サイクルが早い[dataInComp]がデータを取得し損ねているのは、その時だけ
> [dataOutComp]が急にサイクルが早くなり、データを2度書き終えてしまった可能
> 性もありますが、これは考えにくいため、
> [dataOutComp]側がバッファへのデータ書き込みに失敗していると考えているの
> ですが、”ロック”がかかる状況が発生したのでしょうか?
> たとえば、[dataInComp]がisNew()でバッファにアクセスしている最中に、丁度
> [dataOutComp]がデータ書き込みを試みて、ロックがかかっているため失敗した
> など。
> 
>  ちなみに、[dataOutComp]はOpenHRP3のシミュレータとControllBridgeを介し
>  て、毎シミュレーションstep毎(0.002sec)にデータをもらい、そのまま、
> [ dataInComp]にスルーさせる構成です。
> 
> 
> 情報、よろしくお願いします。
> 
> 
> 
> ----------------------------------------------------------------
> [[dataOutComp側のonExecute部(必要部のみ記述)]]
> 
> onExecute(){
> 
>   //データセット
>   unsigned long sec,nsec;
> 
>    ・・・
>      「省略(0.002[sec]毎にシミュレータからデータ取得し、時刻をセット)」
>    ・・・
> 
>   m_dataOut.tm.sec = sec;
>   m_dataOut.tm.nsec = nsec;
> 
>   //データ出力
>   m_dataOut.write();
> 
>   //時刻デバッグ
>   double time = sec + 1.0e-9*nsec;
>   std::cout << "--[送信][TIME]: " << time << std::endl;
> 
>   return RTC::RTC_OK;
> }
> 
> 
> 
> [[dataInComp側のonExecute部(必要部のみ記述)]]
> 
> onExecute(){
> 
>   //新しいデータが得られたら実行
>   if (m_dataIn.isNew()) {
> 
>     //データ取得
>     m_dataIn.read();
> 
>     //データセット
>     unsigned long sec,nsec;
>     sec = m_dataIn.tm.sec;
>     nsec = m_dataIn.tm.nsec;
> 
>     //時刻デバッグ
>     double time = sec + 1.0e-9*nsec;
>     std::cout << "--[受信][TIME]: " << time << std::endl;
> 
>   } else {
>     //新しいデータが得られていないので処理をスキップ
>     std::cout << "---[SKIP] " << std::endl;			
>   } 
> 
>   return RTC::RTC_OK;
> 
> }
> 
> 
> 
> ----------------------------------------------------------------
> <dataOutComp側のデバッグ>
> ・・・
> [送信][TIME]: 0.788 
> [送信][TIME]: 0.79 
> [送信][TIME]: 0.792   <- このデータを送信はきちんとしているはず
> [送信][TIME]: 0.794 
> ・・・
> 
> <dataInComp側のデバッグ>
> ・・・
> [受信][TIME]: 0.788 
> ---[SKIP]
> ---[SKIP]
> ---[SKIP] 
> ---[SKIP] 
> [受信][TIME]: 0.79 
> ---[SKIP]
> ---[SKIP]
> ---[SKIP] 
> ---[SKIP] 
> ---[SKIP] 
>          <--  しかし、この部分のデータの取得が出来ていない(time:0.792)
> [受信][TIME]: 0.794 
> ---[SKIP]
> ---[SKIP]
> ---[SKIP] 
> [受信][TIME]: 0.796 
> ・・・
> 
> 


-- 
----------
栗原 眞二
shinji.kurihara @ aist.go.jp
kurihara @ imagination.co.jp



openrtm-users メーリングリストの案内