ROS2 (intra process communication 2)

ROS2のnodeのあいだの通信を無くします。

Create a custom executable containing multiple nodes which are known at compile time

Writing a couple of Componentやります。

Writing a couple of Component

Setting up efficient intra-process communication

The two node pipeline demo

This demo is designed to show that the intra process publish/subscribe connection can result in zero-copy transport of messages when publishing and subscribing with std::unique_ptrs.

(意訳) unique_ptr使え。

source codeを1行ずつ読もう 1

// Node that produces messages.
struct Producer : public rclcpp::Node
{
  Producer(const std::string & name, const std::string & output)
  : Node(name, rclcpp::NodeOptions().use_intra_process_comms(true))
  {
    // Create a publisher on the output topic.
    pub_ = this->create_publisher<std_msgs::msg::Int32>(output, 10);
    std::weak_ptr<std::remove_pointer<decltype(pub_.get())>::type> captured_pub = pub_;
    // Create a timer which publishes on the output topic at ~1Hz.
    auto callback = [captured_pub]() -> void {
        auto pub_ptr = captured_pub.lock();
        if (!pub_ptr) {
          return;
        }
        static int32_t count = 0;
        std_msgs::msg::Int32::UniquePtr msg(new std_msgs::msg::Int32());
        msg->data = count++;
        printf(
          "Published message with value: %d, and address: 0x%" PRIXPTR "\n", msg->data,
          reinterpret_cast<std::uintptr_t>(msg.get()));
        pub_ptr->publish(std::move(msg));
      };
    timer_ = this->create_wall_timer(1s, callback);
  }

  rclcpp::Publisher<std_msgs::msg::Int32>::SharedPtr pub_;
  rclcpp::TimerBase::SharedPtr timer_;
};

outputにtopic名を入れます。間違えると通信できません。
変更しないclassのconst参照渡しは基本中の基本。
intra process communicationなpublisherの雛形としてはこうなりますよね、という設計。
timerの1s埋め込みだけは解消しておきましょう。

callbackはlambdaと。counter回したいからstaticか。
僕はcallbackは普通の関数書く派です。

source codeを1行ずつ読もう 2

// Node that consumes messages.
struct Consumer : public rclcpp::Node
{
  Consumer(const std::string & name, const std::string & input)
  : Node(name, rclcpp::NodeOptions().use_intra_process_comms(true))
  {
    // Create a subscription on the input topic which prints on receipt of new messages.
    sub_ = this->create_subscription<std_msgs::msg::Int32>(
      input,
      10,
      [](std_msgs::msg::Int32::UniquePtr msg) {
        printf(
          " Received message with value: %d, and address: 0x%" PRIXPTR "\n", msg->data,
          reinterpret_cast<std::uintptr_t>(msg.get()));
      });
  }

  rclcpp::Subscription<std_msgs::msg::Int32>::SharedPtr sub_;
};

inputにtopic名を入れます。間違えると通信できません。

source codeを1行ずつ読もう 3

int main(int argc, char * argv[])
{
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);
  rclcpp::init(argc, argv);
  rclcpp::executors::SingleThreadedExecutor executor;

  auto producer = std::make_shared<Producer>("producer", "number");
  auto consumer = std::make_shared<Consumer>("consumer", "number");

  executor.add_node(producer);
  executor.add_node(consumer);
  executor.spin();

  rclcpp::shutdown();

  return 0;
}

SingleThreadedExecutorを使います。
ここでtopic名を決めてます。

まとめ

・下記の感じでunique_ptr使え。

std_msgs::msg::Int32::UniquePtr

・use_intra_process_comms(true)を追記しろ。(汎用性を持たせたい場合も考えて後の記事で修正します。)

・SingleThreadedExecutor使え。publisherとsubscriberのmain関数は書くな。

などなど。

一番重要なのはpublisherとsubscriberのintra process communicationなsource codeに変更が必要ということかな。
雛形から作成するのが良いでしょう。

publisherとsubscriberとmainのfileを分けて欲しかった。

広告

IT開発関連書とビジネス書が豊富な翔泳社の通販『SEshop』
さくらのレンタルサーバ
ムームードメイン
Oisix(おいしっくす)
らでぃっしゅぼーや
珈琲きゃろっと
エプソムソルト




«       »