0
Help us understand the problem. What are the problem?

posted at

updated at

独自メッセージを用いたROS2 publisher/subscriber:初級 -class style-

ROS2関係トップページへ
ROS2レクチャー:初級 -class style-

【前:ROS2独自メッセージの作成
【次:ROS2の最小構成service/client:初級 -class style-

ここで作成した独自メッセージのうちtopic用メッセージを用いたpublisherとsubscriberのプログラムを作成する.
ここでは一つのパッケージとしてpublisherとsubscriberを作る.

再度掲示:topic用メッセージ

パッケージ名:my_messages
収納ディレクトリ:msg
メッセージファイル名:TwoInts.msg

TwoInts.msg
int64 a
int64 b

上記をビルドしたものなので,以下のように使用できる.

  • インクルードファイル
    • #include "my_messages/msg/two_ints.msg"
  • 型クラス
    • my_messages::msg::TwoInts

準備

terminal
$ cd ~/ros2_studies_ws/
$ ros2 pkg create my_msg_class --dependencies rclcpp my_messages

publisher

作成物:

  • src/my_pub.hpp
  • src/my_pub.cpp
  • src/my_pub_main.cpp

プログラム:src/my_pub.hpp

src/my_pub.hpp
#include <rclcpp/rclcpp.hpp>
#include "my_messages/msg/two_ints.hpp"

class MyPub : public rclcpp::Node{
private:
  rclcpp::Publisher<my_messages::msg::TwoInts>::SharedPtr pub_;
  rclcpp::TimerBase::SharedPtr timer_;
public:
  MyPub(
    const std::string& name_space="", 
    const rclcpp::NodeOptions& options = rclcpp::NodeOptions()
  );
};

概要

作成した独自メッセージを使用.
また必須ではないが,Timerを使用して定期的にメッセージを配信.

説明

2行目:作成したメッセージをインクルード
6行目:作成したメッセージを使ったPublisherを作成

プログラム:src/my_pub.cpp

src/my_pub.cpp
#include <rclcpp/rclcpp.hpp>
#include <rclcpp/qos.hpp>
#include <chrono>
#include "my_messages/msg/two_ints.hpp"
#include "my_pub.hpp"

MyPub::MyPub(
  const std::string& name_space, 
  const rclcpp::NodeOptions& options
): Node("my_pub_test",name_space,options){
  using namespace std::chrono_literals;
  pub_ = this->create_publisher<my_messages::msg::TwoInts>("msg_test",rclcpp::QoS(10));
  timer_ = this->create_wall_timer(
    500ms,
    [this]() ->void {
      auto msg = std::make_shared<my_messages::msg::TwoInts>();
      msg->a = 3;
      msg->b = 4;
      RCLCPP_INFO(this->get_logger(), "Pub: %d, %d",msg->a, msg->b);
      pub_->publish(*msg);
    }
  );
}

概要

独自メッセージは二つのint64型.ここでは適当な数(17行目の3と18行目の4)を発信するだけのもの.

説明

4行目:独自メッセージをインクルード
12行目:独自メッセージを発信するpublisherをトピック名:msg_testで作成
13行目からTimerを使って定期実行
16行目:独自メッセージを宣言
17,18行目:独自メッセージに値を代入
20行目:発信

プログラム:src/my_pub_main.cpp

src/my_pub_main.cpp
#include <rclcpp/rclcpp.hpp>
#include "my_pub.hpp"

int main(int argc, char * argv[]){
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MyPub>());
  rclcpp::shutdown();
  return 0;
}

概要

これまでどおりnodeをつくってspin.

subscriber

作成物:

  • src/my_sub.hpp
  • src/my_sub.cpp
  • src/my_sub_main.cpp

プログラム:src/my_sub.hpp

src/my_sub.hpp
#include <rclcpp/rclcpp.hpp>
#include "my_messages/msg/two_ints.hpp"

class MySub : public rclcpp::Node{
private:
  rclcpp::Subscription<my_messages::msg::TwoInts>::SharedPtr sub_;
public:
  MySub(
    const std::string& name_space="", 
    const rclcpp::NodeOptions& options = rclcpp::NodeOptions()
  );
};

概要

publisherと同様に独自メッセージをインクルードして使用する

プログラム:src/my_sub.cpp

src/my_sub.cpp
#include <rclcpp/rclcpp.hpp>
#include <rclcpp/qos.hpp>
#include "my_messages/msg/two_ints.hpp"
#include "my_sub.hpp"

MySub::MySub(
  const std::string& name_space, 
  const rclcpp::NodeOptions& options
):Node("my_sub_test",name_space,options){
  sub_ = this->create_subscription<my_messages::msg::TwoInts>(
    "msg_test",
    rclcpp::QoS(10),
    [this](const my_messages::msg::TwoInts::SharedPtr msg) ->void {
      RCLCPP_INFO(this->get_logger(), "Sub: %d, %d", msg->a, msg->b);
    }
  );
}

概要

publisherと同様に独自メッセージをインクルードして使用する

プログラム:src/my_sub_main.cpp

src/my_sub_main.cpp
#include <rclcpp/rclcpp.hpp>
#include "my_sub.hpp"

int main(int argc, char * argv[]){
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MySub>());
  rclcpp::shutdown();
  return 0;
}

概要

これまでどおりnodeをつくってspin.

package.xmlとCMakeLists.txt

以下は追加したところに関係する部分のみ抜粋

package.xml

package.xml
<package format="3">
  <depend>rclcpp</depend>
  <depend>my_messages</depend>

依存関係で必要になってくる部分が,自分で作成したmy_messagesというパッケージなので追加.

CMakeLists.txt

CMakeLists.txt
find_package(rclcpp REQUIRED)
find_package(my_messages REQUIRED)

add_executable(my_sub_test
  src/my_sub_main.cpp
  src/my_sub.cpp
)
ament_target_dependencies(my_sub_test
  rclcpp
  my_messages
)

add_executable(my_pub_test
  src/my_pub_main.cpp
  src/my_pub.cpp
)
ament_target_dependencies(my_pub_test
  rclcpp
  my_messages
)

install(TARGETS
  my_sub_test
  my_pub_test
  DESTINATION lib/${PROJECT_NAME}
)

二つのターゲットがあるだけで,これまで通り以下を追加.

  • find
  • add_executable
  • ament_target_dependencies
  • install

ビルド・実行

ビルド

terminal
$ cd ~/ros2_studies_ws/
$ colcon build --symlink-install --packages-up-to my_msg_class
$ . install/local_setup.bash

実行

publisher用のterminalとsubscriber用のterminalを起動.

terminal1
$ cd ~/ros2_studies_ws/
$ . install/local_setup.bash
$ ros2 run my_msg_class my_pub_test
terminal2
$ cd ~/ros2_studies_ws/
$ . install/local_setup.bash
$ ros2 run my_msg_class my_sub_test

独自メッセージと作成プログラムが同一パッケージの場合

基本的には独自メッセージ・ライブラリ・ターゲットは別パッケージが望ましい.
しかし例外はあるものなので,同一パッケージでどうしても,という場合はこちらを参照.
参考:公式tutorialのメッセージに関係するページの一番下.

【前:ROS2独自メッセージの作成
【次:ROS2の最小構成service/client:初級 -class style-

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?