[openrtm-users 00406] Re: リングバッファからのデータ取得につきまして
kurihara shinji
shinji.kurihara @ aist.go.jp
2008年 3月 28日 (金) 15:47:42 JST
産総研 中島様
栗原です。
> また、コールバック実装サンプルのページを記載のある、以下の2行
>
> #include <rtm/RingBuffer.h>
> InPort<TimedLong, RTC::RingBuffer> m_inIn;
>
> を追記が必要と知らず、デフォルトでリングバッファを使用しているものと
> 思い込んでおりました。
> (昨日までは、通常のFIFOバッファを使用していた?)
OpenRTM-aist-0.4.1では、InPort,OutPortともに上記のように明示的にRingBuffer
を指定しなくてもデフォルトでRingBufferが使用される実装となっております。
しかし、現状のRingBufferの実装では、下記のようにwrite()の際にだけ読み込み
用ポインタ、書き込み用ポインタの操作をしているため、連続してwrite()が行わ
れた場合、read()で読めるデータは最後にwrite()したデータだけとなります。
<OpenRTM-aist-0.4.1でのRingBuffer>
r: 読み込み用ポインタ, w: 書き込み用ポインタ
(1回目のwrite)
+---+---+---+---+---+---+
| r | w | | | | | <--- バッファ
+---+---+---+---+---+---+
0 1 2 3 4 5 <--- 要素番号
(2回目のwrite: ここで、r,wポインタ共にインクリメントされます)
+---+---+---+---+---+---+
| | r | w | | | |
+---+---+---+---+---+---+
0 1 2 3 4 5
この時点でread()を行った場合、1回目のwrite()で書き込まれたデータ
要素番号0に格納されておりますが、2回目のwrite()で読み込み用ポイ
ンタが要素番号1を指すようになりますので、要素番号0のデータは取得
する事ができません。
この問題の回避策としましては、write()では書き込み用のポインタだけの
操作を行い、read()の際に読み込み用のポインタを操作するといったリング
バッファを実装し、それをInPort側で使用して頂く事でデータの欠落は無く
なるのではないかと思います。
※ 自作のリングバッファではRingBufferを継承する必要があります。
OpenRTM-aist/rtm/RingBuffer.hを参考にして下さい。
dataInComp.hで以下のように記述する事でユーザー作成のバッファが使用
されるようになります。
#include "MyRingBuffer.h"
InPort<TimedLong, RTC::MyRingBuffer> m_inIn;
以上、宣しくお願い致します。
>
> 産総研の中島です。
>
> 情報提供ありがとうございました。
> 結果は、栗原様の指摘された通りでした。
>
> 早速コールバックの実装をしてトライしたところ、
> [dataInComp]側INPORTのバッファにはデータが正常に
> 入っており[dataOutComp]からの書き込みには問題が
> 無いことが分かりました。
> [dataInComp]の実行サイクルが必ずしも[dataOutComp]より早いわけではなく、
> read()-read()の間に複数回のwrite()があり、データの取得が出来ず結果的に
> 欠落した状態でした。
>
> また、コールバック実装サンプルのページを記載のある、以下の2行
>
> #include <rtm/RingBuffer.h>
> InPort<TimedLong, RTC::RingBuffer> m_inIn;
>
> を追記が必要と知らず、デフォルトでリングバッファを使用しているものと
> 思い込んでおりました。
> (昨日までは、通常のFIFOバッファを使用していた?)
>
> 今回コールバックの実装に併せて追記しましたが、通常のバッファ/リングバッファ
> の両方でテストしても、結果は同じでした。
>
>
> ---
> 少し話しがRTMのMLの趣旨からずれますが、今回は、
>
> [OpenHRP3]----------[dataOutComp]---[dataInComp]---[他のコンポーネント]
> ↑ControllBridgeで接続
>
> の構成でコンポーネントを走らせてシミュレーション値をデータポートで取得し
> ようとしておりましたが、
>
> [dataInComp]実行周期は、”rtc.conf”内で「exec_cxt.periodic.rate」の値を
> 調整できると思いますが(今回はデフォルト1000で実施)
>
> [dataOutComp]は”rtc.conf”内で「exec_cxt.periodic.type」に
> 'OpenHRPExecutionContext'を指定し使用していたので、実行周期は
> [dataInComp]と同期せず、デバッグしている限りでは、シミュレーションが
> 軽い場合(例えば何も処理しなかった)ではサイクルが早く、不定期にデータ
> をwrite()しているように思えました。そのため、[dataInComp]側が定周期で
> read()していては、データ待ちをしたり、取りこぼしたりという状態が発生
> するものかと思われます。
>
> もし、OpenHRPを同じ用に使用している方で、何か情報がありましたら、お願いします。
>
>
>
> > 産総研 中島様
> >
> > 産総研タスクグループ 栗原です。
> >
> > > [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
>
> -----------------------------------------------------
> 〒305-8568
> 茨城県つくば市梅園1-1-1 つくば中央第2 2-12棟
> 独立行政法人 産業技術総合研究所
> 知能システム研究部門 自律行動制御研究グループ
>
> 中島 裕介 (Yusuke Nakajima)
>
> TEL:029-861-5080(内線55267)
> mailto:y.nakajima @ aist.go.jp
> -----------------------------------------------------
>
--
----------
栗原 眞二
shinji.kurihara @ aist.go.jp
kurihara @ imagination.co.jp
openrtm-users メーリングリストの案内