2020年6月18日木曜日

ROS2で複数ドメインID通信を行う方法

ROS2で複数ドメインIDを通信する方法は、環境変数ROS_DOMAIN_IDを変更して、NodeOptionsを
生成し、それをNode生成時に引数で渡す。

------- 以降、ソース例


#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <chrono>
#include <iostream>

using namespace std::chrono_literals;
class Talker : public rclcpp::Node
{
public:
explicit Talker(const std::string& node_name,
const rclcpp::NodeOptions& options=rclcpp::NodeOptions()):Node(node_name,options)
{
//送信するメッセージ
msg_ = std::make_shared<std_msgs::msg::String>();
msg_->data = "Hello World!-"+node_name;

//タイマー実行されるイベントハンドラ関数
auto publish_message = [this]()-> void //ラムダ式による関数オブジェクトの定義
{
RCLCPP_INFO(this->get_logger(),"%s",this->msg_->data.c_str());
this->pub_->publish(msg_);
};

//chatterトピックの送信設定
pub_ = create_publisher<std_msgs::msg::String>("chatter");

//publish_messageの100ミリ秒周期でのタイマー実行
timer_ = create_wall_timer(100ms,publish_message);
}

private:
std::shared_ptr<std_msgs::msg::String> msg_;
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_;
rclcpp::TimerBase::SharedPtr timer_;
};
#ifndef NOMAIN
int main(int argc,char* argv[])
{
//クライアントライブラリの初期化
setvbuf(stdout,NULL,_IONBF,BUFSIZ);
rclcpp::init(argc,argv);
rclcpp::executors::SingleThreadedExecutor exec;
//talkerノードの生成とスピン開始
rclcpp::NodeOptions options;
std::cout << "domain_id=" << options.get_rcl_node_options()->domain_id << std::endl;

auto node = std::make_shared<Talker>("talker",options);
setenv("ROS_DOMAIN_ID","10",1);
rclcpp::NodeOptions options2;
std::cout << "domain_id=" << options.get_rcl_node_options()->domain_id << std::endl;
std::cout << "domain_id2=" << options2.get_rcl_node_options()->domain_id << std::endl;
auto node10 = std::make_shared<Talker>("talker10");
unsetenv("ROS_DOMAIN_ID");
auto node0_1 = std::make_shared<Talker>("talker0_1",options);
auto node10_1 = std::make_shared<Talker>("talker10_1",options2);
exec.add_node(node);
exec.add_node(node10);
exec.add_node(node0_1);
exec.add_node(node10_1);
exec.spin();
rclcpp::shutdown();

return(0);
}
#endif