Download
latest Releases : 2.0.0-RELESE
2.0.0-RELESE | Download page |
Number of Projects
RT-Component | 153.5 |
RT-Middleware | 35 |
Tools | 22 |
Documentation | 2 |
Choreonoid
Motion editor/Dynamics simulator
OpenHRP3
Dynamics simulator
OpenRTP
Integrated Development Platform
AIST RTC collection
RT-Components collection by AIST
TORK
Tokyo Opensource Robotics Association
DAQ-Middleware
Middleware for DAQ (Data Aquisition) by KEK
OpenRTM-aist開発者各位
静岡大の清水です。
コンポーネントのonExecute()から自身をdeactivateした場合、
現行のECの実装では、deactivate_component()がタイムアウト付きの
同期呼び出しになっているため、必ずタイムアウト時間(10秒)
待たせられます。
さらに、deactivate_component()の戻り値がERRORとなります。
基本的には、deactivate_component()は同期呼び出しの方が
よいと思いますが、上記のように、コンポーネント内部から
自分をdeactivateしたい場合はデッドロックの問題が発生します。
そこで、対処策を考えてみました。
デッドロックが起きるケースは、
あるECが駆動しているRTCの内部から、
そのECが駆動しているRTCのdeactivateを行った場合のみです。
すなわち、deactivate_component()の呼び出し元のスレッドと、
ECのスレッドが同一である場合のみデッドロックが起きます。
よって、deactivate_component()の呼び出し元のスレッドIDと
ECのスレッドIDが一致するかを確認して、
一致する場合は非同期呼び出し、
一致しない場合は同期呼び出しとなるように実装すれば
問題を回避できるはずです。
試しに、Linux(POSIX)環境で上記の実装を行ってみました。
OpenRTM1.1.1のC++ソースとの差分を添付します。
見てもらえればわかりますが、実装は簡単です。
とりあえず、POSIX用しか実装していませんが、
Windowsでも同様の実装ができるはずです。
また、OSによる実装の違いはcoilで吸収できるので、
RTMコアの汎用性やportabilityは保証されます。
上記の実装が上手く機能するか、
以下のようなRTCでテストしてみました。
onExecute()が10000回呼ばれたら自動でdeactivateするという実装です。
onExecute(UniqueId ec_id)
{
ReturnCode_t ret(RTC_OK);
m_tick++;
if (m_tick > 10000) {
ExecutionContext_var ec;
ec = this->get_context(ec_id);
ret = ec->deactivate_component(this->getObjRef());
}
return ret;
}
テストした結果、上記のパッチを当てたRTMでは、
タイムアウト待ちなしでdeactivateに成功しました。
また、RTSEからdeactivateした場合(別プロセスからdeactivateした場合)は
deactivate_component()は同期呼び出しとなり、
この場合も問題なくdeactivateできました。
以上、deactivate_component()の実装を検討してもらえると幸いです。
清水