void registerPort(CorbaPort& port); bool addPort(PortBase& port); bool addPort(PortService_ptr port); bool addPort(CorbaPort& port); bool addInPort(const char* name, InPortBase& inport); bool addOutPort(const char* name, OutPortBase& outport);
| ポートの登録: 既存の registerPort などのメンバ関数との違いは、登録の成否を |
戻り値で返すか否かである。登録が失敗するのは既に同じポート名や
同じポートのインスタンスが登録されていた場合である。
それ以外の機能は同じである。bool removePort(PortBase& port); bool removePort(PortService_ptr port); bool removeInPort(InPortBase& port); bool removeOutPort(OutPortBase& port); bool removePort(PortBase& port); bool removePort(PortService_ptr port); bool removePort(CorbaPort& port);
| ポートの登録解除: 既存の deletePort などのメンバ関数との違いは、登録の成否を戻り値で返すか否かである。 |
登録が失敗するのは既に同じポート名や同じポートのインスタンスが登録されていた場合である。 それ以外の機能は同じである。
bool readAll();
class DataIn: public RTC::DataFlowComponentBase
{
RTC::TimedLong input_data1_;
RTC::InPort<RTC::TimedLong> inport1_;
RTC::TimedLong input_data2_;
RTC::InPort<RTC::TimedLong> inport2_;
public:
explicit DataIn(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
input_data1_(),
inport1_("inport1", input_data1_),
input_data2_(),
inport2_("inport2", input_data2_)
{
}
virtual RTC::ReturnCode_t onInitialize()
{
registerInPort("inport1", inport1_);
registerInPort("inport2", inport2_);
return RTC::RTC_OK;
}
virtual RTC::ReturnCode_t onExecute(RTC::UniqueId exec_handle)
{
// inport1_とinport2_に対してreadを呼び出す
const bool is_read_success = readAll();
if (is_read_success)
{
std::cout << input_data1_.data << std::endl;
std::cout << input_data2_.data << std::endl;
}
return RTC::RTC_OK;
}
};
bool writeAll(); class DataOut: public RTC::DataFlowComponentBase
{
RTC::TimedLong output_data1_;
RTC::OutPort<RTC::TimedLong> outport1_;
RTC::TimedLong output_data2_;
RTC::OutPort<RTC::TimedLong> outport2_;
public:
explicit DataOut(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
output_data1_(),
outport1_("outport1", output_data1_),
output_data2_(),
outport2_("outport2", output_data2_)
{
}
virtual RTC::ReturnCode_t onInitialize()
{
registerOutPort("outport1", outport1_);
registerOutPort("outport2", outport2_);
return RTC::RTC_OK;
}
virtual RTC::ReturnCode_t onExecute(RTC::UniqueId exec_handle)
{
output_data1_.data += 2;
output_data2_.data += 3;
// outport1_とoutport2_に対してwriteを呼び出す
const bool is_write_success = writeAll();
if (!is_write_success)
{
std::cout << "write fail" << std::endl;
}
return RTC::RTC_OK;
}
};
void setReadAll(bool read=true, bool completion=false); class DataIn: public RTC::DataFlowComponentBase
{
RTC::TimedLong input_data1_;
RTC::InPort<RTC::TimedLong> inport1_;
RTC::TimedLong input_data2_;
RTC::InPort<RTC::TimedLong> inport2_;
public:
explicit DataIn(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
input_data1_(),
inport1_("inport1", input_data1_),
input_data2_(),
inport2_("inport2", input_data2_)
{
}
virtual RTC::ReturnCode_t onInitialize()
{
registerInPort("inport1", inport1_);
registerInPort("inport2", inport2_);
setReadAll(); // ★
return RTC::RTC_OK;
}
virtual RTC::ReturnCode_t onExecute(RTC::UniqueId exec_handle)
{
// onExecuteが呼び出される直前にinport1_とinport2_のreadが呼ばれている
std::cout << input_data1_.data << std::endl;
std::cout << input_data2_.data << std::endl;
return RTC::RTC_OK;
}
};void setWriteAll(bool write=true, bool completion=false);
class DataOut: public RTC::DataFlowComponentBase
{
RTC::TimedLong output_data1_;
RTC::OutPort<RTC::TimedLong> outport1_;
RTC::TimedLong output_data2_;
RTC::OutPort<RTC::TimedLong> outport2_;
public:
explicit DataOut(RTC::Manager* manager):
RTC::DataFlowComponentBase(manager),
output_data1_(),
outport1_("outport1", output_data1_),
output_data2_(),
outport2_("outport2", output_data2_)
{
}
virtual RTC::ReturnCode_t onInitialize()
{
registerOutPort("outport1", outport1_);
registerOutPort("outport2", outport2_);
setWriteAll(); // ★
return RTC::RTC_OK;
}
virtual RTC::ReturnCode_t onExecute(RTC::UniqueId exec_handle)
{
output_data1_.data += 2;
output_data2_.data += 3;
return RTC::RTC_OK;
// onExecuteを抜けた直後にoutport1_とoutport2_のwriteが呼ばれる
}
}; class MyDataListener
: public ConnectorDataListenerT<RTC::TimedLong>
{
public:
virtual void operator()(const ConnectorInfo& info,
const TimedLong& data)
{
// コールバックの処理
};
};MyDataListener *listner = new MyDataListener(); m_port.addConnectorDataListener(ON_BUFFER_WRITE, listner);
m_port.removeConnectorDataListener(ON_BUFFER_WRITE, listner);
class MyConnectorListener
: public ConnectorListener
{
public:
virtual void operator()(const ConnectorInfo& info)
{
// コールバックの処理
};
};MyConnectorListener *listner = new MyConnectorListener(); m_port.addConnectorListener(ON_BUFFER_EMPTY, listner);
m_port.removeConnectorListener(ON_BUFFER_EMPTY, listner);
void setOnPublishInterfaces(ConnectionCallback* on_publish);
void setOnSubscribeInterfaces(ConnectionCallback* on_subscribe);
void setOnConnected(ConnectionCallback* on_connected);
ミューテックスがロックされているため、コールバック内で、
コールバックを設定したポートに対してget_connector_profilesや
get_port_profileなどを呼び出すとデッドロックすることに注意。
コールバックを設定したポート以外のポートに対しては
ミューテックスがロックされていないため、get_port_profileなどの
呼び出しは可能。
例えば、ポート1とポート2を接続することを考える。
ポート1にsetOnConnectedでコールバックを設定しておく。
このコールバック内からポート1に対してget_port_profileなどの
呼び出しを行うとデッドロックする。ポート2に対しては
get_port_profileなどを呼び出せる。void setOnUnsubscribeInterfaces(ConnectionCallback* on_subscribe);
ミューテックスがロックされているため、コールバック内で、
接続対象ポートのget_connector_profilesやget_port_profileなどを
呼び出すとデッドロックすることに注意。
setOnConnectedと違い、コールバックを設定していないポートに
対してもget_port_profileなどを呼び出せないことに注意。
例えば、ポート1とポート2を接続することを考える。
ポート1にsetOnConnectedでコールバックを設定しておく。
このコールバック内からはポート1、ポート2ともに
get_port_profileなどの呼び出しを行うとデッドロックする。void setOnDisconnected(ConnectionCallback* on_disconnected);
切断処理の途中に何らかのエラーがあってもコールバックは
呼び出されることに注意。
また、ミューテックスのロックされているため、
setOnUnsubscribeInterfacesと同様、デッドロックに注意。void setOnConnectionLost(ConnectionCallback* on_connection_lost);
ただし、このコールバックに関しては、PortBaseでは処理の実装を
しておらず、派生クラス側で実装するようになっている。
現在は、OutPortのみに実装されており、InPortとCorbaPortでは
コールバックを設定しても呼び出されることはない。ただし、addPortやregisterPortなどでポートをRTCに登録していない状態では、.[ポート名]になっている。 また、addPortやregisterPortなどの呼び出しをonInitialize以前(コンストラクタなど)で行うと、 RTCのインスタンス名が確定していないため、ポート名は .[ポート名]になってしまう。
subscribeInterfacesの呼び出しについて、途中で1つでも失敗した場合、
即座にエラー復帰する subscribeInterfacesの呼び出しについて、途中で失敗しても、
そのまま処理は続行する。接続対象ポート全てに対して処理を
行った後、発生したエラーに対応するエラー戻り値を返す。const char* getName() const;
・PortBaseのprotectedメンバ関数eraseConnectorProfileが
ミューテックスのロックを行わなくなった。
・PortBaseの以下のメンバ関数を呼び出した際、
接続しているポートを全てチェックし、無効になったポートが あれば、切断処理を行うようになった。 get_port_profile() get_connector_profiles() get_connector_profile()
・ポートのプロパティ"connection_limit"を指定すると、
接続数の制限ができるようになった。
■データポート 【コールバック関連】 ・InPortの以下のコールバック設定関数が削除された。
その代わり、addConnectorDataListenerを使用する。 void setOnWrite(OnWrite<DataType>* on_write); void setOnWriteConvert(OnWriteConvert<DataType>* on_wconvert); void setOnOverflow(OnOverflow<DataType>* on_overflow); void setOnUnderflow(OnUnderflow<DataType>* on_underflow);
・OutPotの以下のメンバ関数が削除された。
コールバックの設定はaddConnectorDataListenerを使用する。 bool read(DataType& value); void setReadBlock(bool block); void setWriteBlock(bool block); void setReadTimeout(long int timeout); void setWriteTimeout(long int timeout); void setOnOverflow(OnOverflow<DataType>* on_overflow); void setOnRead(OnRead<DataType>* on_read); void setOnReadConvert(OnReadConvert<DataType>* on_rconvert); void setOnUnderflow(OnUnderflow<DataType>* on_underflow); void setOnConnect(OnConnect* on_connect); void setOnDisconnect(OnConnect* on_disconnect); void onConnect(const char* id, PublisherBase* publisher); void onDisconnect(const char* id);
【接続時のポリシ設定】 ・RT System Editorでデータポートを接続する際、
送信ポリシとバッファリングポリシを指定できるようになった。
送信ポリシ(接続方式がflush(デフォルト)の場合は使えない) - All: InPortのバッファにたまっているデータを一度にすべて送信する - Fifo: InPortのバッファにたまっているデータをFIFOとみなして(古い方から1つず
- Skip: InPortのバッファにたまっているデータを間引いて送信する - New: InPortのバッファにたまっているデータの最新値のみを送信する
バッファリングポリシ ・バッファ書き込み時にバッファがフルだった場合の動作を指定できる。 - overwrite: 上書きする - do_nothing: 何もしない - block: ブロックする。タイムアウト設定可。
・バッファ読み込み時にバッファが空だった場合の動作を指定できる。 - readback: 最新の値を読み直す - do_nothing: 何もしない - block: ブロックする。タイムアウト設定可。
・データポートの接続時のプロパティに"dataport.serializer.cdr.endian"
を指定すると、送受信するデータのエンディアンを変更できる。 しかし、RT System Editorは対応していない。
【その他】 ・DataPortStatusにBUFFER_ERRORが追加された。
・データポートでCORBAの代わりにTCP/IPを用いて通信を行うことが
できなくなった。 (TCP/IP用のProvider/Consumerを自作すれば可能だと思われる)
・InPort::readの戻り値の型が変更された。
(RC1) 読み込んだデータ (RELEASE) 読み込みの成否を表すbool
・Timed*のデータに対して現在時刻を付与する関数setTimestamp()が追加された。
・OutPort::write()で、タイムスタンプを付与しなくなった。
・OutPotに以下のメンバ関数が追加された。
これを用いると、1対多接続の際に接続ごとのwriteの結果が取得できる。 DataPortStatus::Enum getStatus(int index); DataPortStatusList getStatusList();
・データポートのpullの動作
- InPort::isNew()は常にfalseを返す。 - 送信側のバッファにデータがない場合は、InPort::read()の戻り値がfalseになる。 - OutPort側のBuffer empty policyの設定により、バッファが空だった場合の動作が異なる。 デフォルトではreadbackになっているため、一度データをwrite()すると同じ値を読み続
データポートをpushで接続した場合と、pullで接続した場合ではプログラミングスタイ
[pushの場合]
RTC::ReturnCode_t ConsoleOut::onExecute(RTC::UniqueId ec_id) {
if (m_inport.isNew()) {
m_inport.read();
// データを利用した処理
}
return RTC::RTC_OK;
} [pullの場合]
RTC::ReturnCode_t ConsoleOut::onExecute(RTC::UniqueId ec_id) {
bool ret = m_inport.read();
if (ret == true) {
// データを利用した処理
}
return RTC::RTC_OK;
}■サービスポート 【接続時のポリシ設定】 ・CorbaPortの接続において、ConnectorProfile::propertiesに
"port.connection.strictness"というプロパティを設定できるようになった。 このプロパティには"strict"か"best_effort"を設定する。 CorbaPort.hより引用 * strict: すべてのコンシューマに指定した参照が存在し、かつナローイン * グにも成功しコンシューマに適切にセットできた場合にのみ Port * 間の接続を確立する。 * * best_effort: ナローイング等に失敗した場合でも、エラーを返すことな * く Port 間の接続を確立する。
【その他】 ・CorbaPortで、接続中にRTCをActivate、Deactivateし、再度Activateすると
コンシューマ側からアクセスできない問題が解消された。
■Manager関係 Managerにマスターとスレーブという関係ができた。 詳細は[openrtm-users 01099]の安藤様の解説を参照のこと。
【rtc.confに与えるプロパティの変更】 ・Managerのプロパティ(rtc.confに与えるプロパティ)に変更があった。
"corba.endpoint" 使用できなくなった。代わりに"corba.endpoints"を使用することになった。
"manager.is_master" NOにするとManagerのCORBAオブジェクトをネーミングサービスに 登録しないようになった。
"manager.corba_servant" NOにするとManagerのCORBAオブジェクトを生成しない。
"manager.is_master" YESであれば、Managerのプロパティ"corba.master_manager"で 指定されているポート番号をORBのエンドポイントとして 追加するようになった。
"manager.shutdown_on_nortcs" YESの場合、"manager.is_master"NOであれば、プロセス内のRTCが0個に なったタイミングでManagerが自動終了するようになった。 ただし、[openrtm-users 01149]のパッチをあてること。
【RTC起動時のコマンドライン引数のオプションの追加】
-a
指定すると、ManagerのCORBAオブジェクトを生成しない。
ただし、ManagerConfig::parseArgs()にバグがあるため、
このオプションを指定してもManagerのCORBAオブジェクトの
生成が有効になる。("maanger.corba_servant"でスペルミス)
SVNの最新ソースでは修正されている模様。
-d
指定すると、Managerがマスターになる。
-o
Managerのプロパティを追加できる。
このオプションに続けて (プロパティのキー):(プロパティの値)と書く。
例えば、-o test.property:100
-p
Managerのプロパティ"corba.endpoints"にポート番号を追加する。
例えば、-p 50000【Managerの内部実装の変更】 ・RC1では未実装だったModuleManager::getLoadableModules()が実装された。
→ Manager::getLoadableModules()が使えるようになった。
・Manager::setModuleInitProc()で設定した関数が実行される
タイミングが変更された。 Manager::activateManager()で実行されること自体は変更されていない。 しかし、Managerのプロパティ"manager.components.precreate"で 指定されたRTCを起動する処理との順番が変更されている。 (RC1) "manager.components.precreate"のRTCを生成した後 (RELEASE) "manager.components.precreate"のRTCを生成する前
・ManagerにRTCのガベージコレクションのような機能が追加された。
RTCをexitすると、Managerが1秒周期でexitされたRTCをdeleteする。 ただし、バグあり。[openrtm-users 01149]のパッチをあてること。 また、createComponentで生成したRTCがon_initializeで失敗すると そのRTCはdeleteされず、メモリリークする。 RTCのinitializeが失敗するとRTCをexitするが、 exitはinitializeが成功していないと処理を拒否するため、 Manager::notifyFinalizedが呼ばれず、Managerの RTCガベージコレクションが働かないため。
・ManagerがRTCを削除する際、deleteを直接使うのではなく、
Manager::registerFactoryで登録されたRTC削除関数を使うように 修正された。
・Manager::load()で、第2引数の初期化関数名が空の場合の処理が追加された。
初期化関数名が空の場合は、第1引数のモジュール名に"Init"を付与した 初期化関数名でモジュールのロードを試みるようになった。
・Manager::createComponentで、指定したRTCを生成するFactoryが
登録されていない場合、Managerのプロパティ"manager.modules.load_path"で 指定したパスから、指定したRTCを生成可能なモジュールを検索し、 自動ロードする機能が追加された。
【IDLインタフェースの変更】 ・IDLインタフェースRTM::Managerが変更された。
(追加) boolean is_master(); ManagerList get_master_managers(); RTC::ReturnCode_t add_master_manager(in Manager mgr); RTC::ReturnCode_t remove_master_manager(in Manager mgr); ManagerList get_slave_managers(); RTC::ReturnCode_t add_slave_manager(in Manager mgr); RTC::ReturnCode_t remove_slave_manager(in Manager mgr); (削除) Manager get_owner(); Manager set_owner(in Manager mgr); Manager get_child(); Manager set_child(in Manager mgr);
・ManagerServant::get_loadable_modules()、
ManagerServant::get_loaded_modules()、 ManagerServant::get_factory_profiles()は、本来、 自分のものだけでなく、スレーブのモジュールも 取得できるようなメソッドのようだが、 現在の実装では自分のモジュールしか取得できない。