IWATAKU
December 12, 2023, 7:31am
1
初めまして。研究でChoreonoid 2.0.0を使用させていただいています。
2つのSimpleControllerのinitialize関数で、rclcpp::init(0, nullptr);
を呼び出していますが、この場合Choreonoidが強制終了し、次のようなエラーメッセージが表示されます。
terminate called after throwing an instance of 'rclcpp::ContextAlreadyInitialized'
what(): context is already initialized
中止
次に、片方のSimpleControllerのinitialize関数をコメントアウトすると、次のようなエラーメッセージが表示されます。
terminate called after throwing an instance of 'rclcpp::exceptions::RCLInvalidArgument'
what(): failed to create guard condition: context argument is null, at ./src/rcl/guard_condition.c:65
中止 (コアダンプ)
2つのSimpleControllerで、ROSのノードをそれぞれ作成したい場合は、どのようにすればいいでしょうか?ご回答いただけると幸いです。よろしくお願いいたします。
IWATAKU
December 12, 2023, 7:38am
2
追記です。initialize関数のあとには、ノードを作成する関数node = rclcpp::Node::make_shared("hoge_controller");
を呼んでいます。
こんばんは、choreonoid_rosのROS 2版を開発している者です。
rclcppとchoreonoid pluginの初期化関数の記述が混在していてソースコードの状況を正しく理解できているのか怪しいのですが、一旦以下のようなソースコードを仮定します。
(お手元のソースコードの状況と私の理解が違いそうでしたら指摘いただけると幸いです)
class SimpleController1 : public SimpleController
{
public:
virtual bool initialize(SimpleControllerIO* io) override
{
// コメントアウトした
// rclcpp::init(0, nullptr);
node = rclcpp::Node::make_shared("hoge_controller");
}
};
class SimpleController2 : public SimpleController
{
public:
virtual bool initialize(SimpleControllerIO* io) override
{
rclcpp::init(0, nullptr);
node = rclcpp::Node::make_shared("hoge_controller");
}
};
このような状況の場合、ノードを作成する前に必ずrclcpp::initを呼び出すことが必要であることを考えると2つあるSimpleControllerのうちコメントアウトしていない方(SimpleController2)が先に初期化されることを保証する必要があります。
初期化の順番が守られなかった場合、2つ目のエラーを出すことがあるようです。
参考:URL
この場合、どうにかしてプラグインの初期化順を固定することも考えられますが、
以下のようにしてSimpleControllerの初期化順に関係なくrclcppを正しく初期化できるようにするのが良いと思います。
virtual bool initialize(SimpleControllerIO* io) override
{
if(!rclcpp::ok()) {
rclcpp::init(0, nullptr);
}
node = rclcpp::Node::make_shared("hoge_controller");
}
IWATAKU
December 12, 2023, 12:49pm
4
ご返信ありがとうございます!
質問時は、提供していただいたコード例の通りとなっており、rclcpp::ok()
にて解決しました。
初歩的な質問でして、申し訳ないです。
的確なご指摘、ありがとうございました。