Closed ketaro-m closed 10 months ago
"sample_service_rtc"において誤植と思われるものを発見しました.
README.md #L129, README.md #L271のいずれにおいても
class ServerService_impl
: public virtual POA_MySample::MyOriginalService,
public virtual PortableServer::RefCountServantBase
となっているものは,
class ServerService_impl
: public virtual POA_sample_service_rtc::MyOriginalService,
public virtual PortableServer::RefCountServantBase
{
であると思います.(ServerService_impl.h
のファイル自体はそうなっています)
MyServer.cpp
#L12にある以下の記述において,"service0"
という名前は固定なのですね.
ソースコードのどこにも"service0"
という記述をいれずにビルドしてもsrc_gen/MyBridgeServiceROSBridge.cpp
にstd::string port_name = "service0";
という固定記述が作られるようで,おそらくOpenHRPの(バージョンによると思いますが)仕様なのだと理解しています.
RTC::ReturnCode_t MyServer::onInitialize(){
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0);
addPort(m_MyServerServicePort);
return RTC::RTC_OK;
}
そして,このポートを"MyBridgeService"という名前でProviderポートとして登録するのがこの行で,server.launch
内でこのようにconnectするときの名前に相当するという理解で正しいでしょうか.
<rtconnect from="MyServer0.rtc:service0" to="MyBridgeServiceROSBridge.rtc:MyBridgeService" />
初見で見たときに,すぐ上でserviceポートを初期化している箇所#L6で指定する名前と同一であるため,このポートのことを差しているのかと混同してしまいました…
MyServer::MyServer(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
m_MyServerServicePort("service0")
{
m_service0.setComponent(this);
}
困惑を避ける意味と理解を促すために,以下のようにポート名の変更とコメントを追加するのはいかがでしょうか.
#include "MyServer.h"
#include <iostream>
MyServer::MyServer(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
m_MyServerServicePort("MyServerService")
{
m_service0.setComponent(this);
}
RTC::ReturnCode_t MyServer::onInitialize(){
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0); // "service0"は固定
addPort(m_MyServerServicePort);
return RTC::RTC_OK;
}
<rtconnect from="MyServer0.rtc:MyServerService" to="MyBridgeServiceROSBridge.rtc:MyBridgeService" />
ありがとうございます。フィードバックをいただけてとても助かります。
"sample_service_rtc"において誤植と思われるものを発見しました.
ありがとうございます。修正しました。
"sample_service_bridge"についての注意書き
いいえ、違います。
サンプルパッケージは、3つのことをしています。
1に対して2と3は依存しています. が、2と3は独立であって、互いに影響を全く与えません。MyServerのソースコードを変えても、生成されるROSBridgeには影響は全くありません。この点が伝わっていない気がします。
server.launch内で
<rtconnect from="MyServer0.rtc:service0" to="MyBridgeServiceROSBridge.rtc:MyBridgeService" />
として、3のサーバーの"service0"というproviderポートと、2のROSBridgeの"MyBridgeService"というconsumerポートを接続しています。
3のサーバーのproviderポートの名前を"service0"と名付けているのは、https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/sample_service_bridge/rtc/MyServer/MyServer.cpp#L6 です。https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/sample_service_bridge/rtc/MyServer/MyServer.cpp#L12 に書いてある"service0"は、ただの飾りです。https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/Writing_Simple_Service_Server_Client_RTC.md?plain=1#L211 とhttps://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/Writing_Simple_Service_Server_Client_RTC.md?plain=1#L220 に説明があります。
2のROSBridgeのconsumerポートの名前"MyBridgeService"ですが、これは、rtmbuildがidlからROSBridgeを自動生成するときに、idlに書かれたinterface名がポート名になるようにする仕様になっています。https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/Creating_Service_ROS_Bridge_Automatically.md?plain=1#L42-L43 に説明があります。自動生成スクリプトのhttps://github.com/start-jsk/rtmros_common/blob/57331a5179d0d10947ff6f58eae744aa8c0be22a/rtmbuild/scripts/idl2srv.py#L495 で指定しています。
ソースコードのどこにも"service0"という記述をいれずにビルドしてもsrc_gen/MyBridgeServiceROSBridge.cppにstd::string port_name = "service0";という固定記述が作られるようで,おそらくOpenHRPの(バージョンによると思いますが)仕様なのだと理解しています.
ここはMyServerのソースコードなので、MyBridgeServiceROSBridge側の名前には一切関係がありません。
ROSBridge内で自動生成されるstd::string port_name = "service0";という固定記述ですが、registerConsumer関数でしか使っていないので、ポート名とは一切関係のないただの飾りです。(https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/Writing_Simple_Service_Server_Client_RTC.md?plain=1#L538 に説明があります。)
そして,このポートを"MyBridgeService"という名前でProviderポートとして登録するのがこの行で,
RTC::ReturnCode_t MyServer::onInitialize(){
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0);
addPort(m_MyServerServicePort);
return RTC::RTC_OK;
}
いいえ。この第一引数service0
は飾りで、registerProvider
の第二引数にはidlに定義されているインターフェースの型名です。https://github.com/Naoki-Hiraoka/rtmros_beginner_tutorial/blob/9fc00a712920c788aff3f80a66bc99b1ef64d0dc/openrtm_beginner_tutorial/Writing_Simple_Service_Server_Client_RTC.md?plain=1#L220 に説明があります。
"service0"という名前でProviderポートとして登録するのは、
MyServer::MyServer(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
m_MyServerServicePort("service0")
{
m_service0.setComponent(this);
}
ここで登録された"service0"という名前が、server.launch内でfrom="MyServer0.rtc:service0"
とconnectするときの名前に相当します.
初見の方もわかるようにするためには、どこの記述を直したらよいと思いますか?
ご丁寧な解説ありがとうございます!! 僕のコメントの書き方がわかりにくかったような気がするのですが,僕が理解しきれていなかったのは
2のROSBridgeのconsumerポートの名前"MyBridgeService"ですが、これは、rtmbuildがidlからROSBridgeを自動生成するときに、idlに書かれたinterface名がポート名になるようにする仕様になっています。
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0); に書いてある"service0"は、ただの飾りです。
という点でした.
1.に関しては,僕の読み込みが足りなかったと思います.実際こちらに解説がありましたね…
2.に関してですが,飾りといっても以下の部分でハードコーディングされているので,これは"service0"以外にするとだめということですよね.(実際別のものにするとビルドは通りますがlaunchできなくなりました)
また, サーバーのproviderポートの名前を"service0"と名付けている
m_MyServerServicePort("service0")
と,2.に該当する飾り変数"service0"
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0);
が別のものを差しているというのは初見では混同してしまったので,名前は別にするとその誤解は避けられるかと思います.
以上を踏まえて,下記のような変更はいかがでしょうか.
`registerProvider`の第一引数`service0`は単なる名前であり、何を与えても実用上あまり重要ではない.
は
`registerProvider`の第一引数`service0`は単なる名前であるが,自動生成スクリプトの [rtmros_common/rtmbuild/scripts/idl2srv.py](https://github.com/start-jsk/rtmros_common/blob/57331a5179d0d10947ff6f58eae744aa8c0be22a/rtmbuild/scripts/idl2srv.py#L495) で指定されているため,`service0`にしなければいけない.
のように変える.
#include "MyServer.h"
#include <iostream>
MyServer::MyServer(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
m_MyServerServicePort("MyServerService")
{
m_service0.setComponent(this);
}
RTC::ReturnCode_t MyServer::onInitialize(){
m_MyServerServicePort.registerProvider("service0", "MyBridgeService", m_service0);
addPort(m_MyServerServicePort);
return RTC::RTC_OK;
}
<rtconnect from="MyServer0.rtc:MyServerService" to="MyBridgeServiceROSBridge.rtc:MyBridgeService" />
2.に関してですが,飾りといっても以下の部分でハードコーディングされているので,これは"service0"以外にするとだめということですよね.(実際別のものにするとビルドは通りますがlaunchできなくなりました)
あれ、launchできなくなるとは知りませんでした。InPort/OutPortは名前を何にしても大丈夫だったので、参考 ServicePortの場合をあまり確認していませんでした。
確認の上、修正します。ありがとうございます。
サービスの場合はregisterProvider
等の第一引数のインスタンス名はただの飾りではなく、サーバー側とクライアント側で同じでないといけませんでした。
各所のREADMEを修正し、サンプルのサーバーのproviderポートの名前と飾り変数を分けました。
自作のRTC(manta_rtc)を作りながら詰まったところ(誤植を含めて)報告させていただいきます. PRにすべきであればPRにします.