ROS 2์—์„œ C++ ๊ธฐ๋ฐ˜ publisher๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž!

์ „์ฒด ์ฝ”๋“œ


#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

class MyPublisher : public rclcpp::Node
{
public: 
  MyPublisher() : Node("my_publisher"), count_(0)
  {
    pub_ = this->create_publisher<std_msgs::msg::String>("msg", 10);
    timer_ = this->create_wall_timer(500ms, std::bind(&MyPublisher::timerCallback, this));
  }

private:
  void timerCallback()
  {
    auto msg = std_msgs::msg::String();
    msg.data = "bigbigpark! " + std::to_string(count_);

    RCLCPP_INFO(this->get_logger(), "Publish: %s", msg.data.c_str());
    pub_->publish(msg);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_;
  size_t count_;
};

int main(int argc, char** argv)
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MyPublisher>());
  rclcpp::shutdown();

  return 0;
}

์ฝ”๋“œ๊ฐ€ ์ข€ ROS 1๊ณผ๋Š” ๋น„์Šทํ•œ ๋“ฏ ๋‹ค๋ฅด๋‹ค ?

์ฝ”๋“œ ๋ถ„์„

#include <chrono>
#include <functional>
#include <memory>
#include <string>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

์‹œ๊ฐ„ ๊ด€๋ จ ํ•จ์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ธ chrono
๋ฉ”๋ชจ๋ฆฌ ๋™์  ๋ฐฐ์—ด ํ• ๋‹น ๊ด€๋ จ memory
ํ•จ์ˆ˜๋ฅผ ๊ฐ์ฒด์ฒ˜๋Ÿผ! functional

์•ž์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋„ ๋ญ”๊ฐ€ ํ•„์ˆ˜์ธ ๊ฒƒ ๊ฐ™์•„์„œ.. ์ผ๋‹จ ์Šต๊ด€์ ์œผ๋กœ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ํ•œ๋‹ค


์ด์ œ๋Š” ros/ros.h๊ฐ€ ์•„๋‹Œ rclcpp/rclcpp.hpp๋กœ ๋ฐ”๋€๋“ฏ ํ•˜๋‹ค
๋˜ํ•œ ๋ฉ”์„ธ์ง€ ํŒจํ‚ค์ง€๋ฅผ ์ฝ์–ด์˜ฌ ๋•Œ๋„ std_msgs/String.h์—์„œ std_msgs/msg/string.hpp๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค

๊ทผ๋ฐ.. ROS 2 ํ‘œ๋ฐ•์‚ฌ๋‹˜ ์ฑ…๋ณด๋ฉด ํ—ค๋”ํŒŒ์ผ์˜ ๋„ค์ด๋ฐ ๊ทœ์น™์— ์–ด๊ธ‹๋‚˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€..??


๊ทธ๋ฆฌ๊ณ  std::chrono_literals๋Š” ์‹œ๊ฐ„์„ ์‰ฝ๊ฒŒ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋‹ค
๋„ค์ž„์ŠคํŽ˜์ด์Šค๋Š” ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋ฐ..ใ… 


class MyPublisher : public rclcpp::Node
{
public: 
  MyPublisher() : Node("my_publisher"), count_(0)
  {
    pub_ = this->create_publisher<std_msgs::msg::String>("msg", 10);
    timer_ = this->create_wall_timer(500ms, std::bind(&MyPublisher::timerCallback, this));
  }

private:
  void timerCallback()
  {
    auto msg = std_msgs::msg::String();
    msg.data = "bigbigpark! " + std::to_string(count_++);

    RCLCPP_INFO(this->get_logger(), "Publish: %s", msg.data.c_str());
    pub_->publish(msg);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_;
  size_t count_;
};

ROS 1 ๊ฐ•์˜์—๋Š” ๋ฐ”๋กœ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•ด์„œ ์„ค๋ช…ํ•˜์ง€ ์•Š์•˜๋Š”๋ฐ, ์ด ROS 2๋Š” ์•„๋ฌด๋ž˜๋„ C++์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์ง€์‹์ด ์žˆ๋Š” ์‚ฌ๋žŒ์„ ํƒ€๊ฒŸ์œผ๋กœ ๋งŒ๋“ค์–ด์กŒ๋‹ค
๊ทธ๋ฆฌ๊ณ  rclcpp::Node ๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค


ํŠนํžˆ ํด๋ž˜์Šค ์ƒ์„ฑ์ž์—์„œ ๋…ธ๋“œ ์ด๋ฆ„์„ ์ธ์ž๋กœ ๋ฐ›์•„์„œ ๋ฐ”๋กœ ์„ ์–ธํ•˜๋Š” ๋ถ€๋ถ„์„ ๊ธฐ์–ตํ•ด์ฃผ์ž
๋˜ํ•œ ROS 1์— ์žˆ์—ˆ๋˜ ros::NodeHandle์ด ์—†์–ด์ง€๊ณ  this->create_publisher๋กœ ๋ณ€๊ฒฝ์ด ๋˜์—ˆ๋‹ค


ROS 1์—์„œ๋Š” main ๋ฌธ ์•ˆ์—์„œ while ๋ฌธ์„ ๋Œ๋ฆฌ๋ฉด์„œ publish๋ฅผ ํ–ˆ๋‹ค๋ฉด, ROS 2์—์„œ๋Š” timer๋ผ๋Š” ๊ฒƒ์„ ์ด์šฉํ•˜์—ฌ publish ์ฝ”๋“œ๋ฅผ ์งค ๋•Œ callback ํ•จ์ˆ˜๋ฅผ ๋Œ๋ฆฐ๋‹ค
์ฆ‰, ๋”์šฑ ์ •ํ™•ํ•œ ์‹œ๊ฐ„์— publishํ•˜๊ฒ ๋‹ค๋Š” ์˜๋ฏธ๋‹ค. ๋”ฐ๋ผ์„œ ์ € ์ฝ”๋“œ๋Š” 500ms ๋งˆ๋‹ค ํƒ€์ด๋จธ๋ฅผ ์ˆ˜์‹ ํ•˜๋Š”๋ฐ, ๊ทธ ๋•Œ๋งˆ๋‹ค count๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๋ฉด์„œ ๋ฉ”์„ธ์ง€๋ฅผ publishํ•œ๋‹ค๋Š” ๋œป์ด ๋œ๋‹ค


private:
  void timerCallback()
  {
    auto msg = std_msgs::msg::String();
    msg.data = "bigbigpark! " + std::to_string(count_++);

    RCLCPP_INFO(this->get_logger(), "Publish: %s", msg.data.c_str());
    pub_->publish(msg);
  }
  rclcpp::TimerBase::SharedPtr timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_;
  size_t count_;

์ด ๋ถ€๋ถ„์€ callback ํ•จ์ˆ˜์ด๊ธด ํ•œ๋ฐ, ROS_INFO ์—์„œ RCLCPP_INFO๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค
๋˜ํ•œ this->get_logger()๋ฅผ ์ œ๊ณตํ•˜๋ฉด์„œ, ๋กœ๊น…์— ๋Œ€ํ•ด์„œ๋„ ๊ฐœ์„ ์ด ์ด๋ฃจ์–ด์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค


๊ทธ๋ฆฌ๊ณ  ํƒ€์ด๋จธ ๋ณ€์ˆ˜์™€ ํผ๋ธ”๋ฆฌ์…” ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ sharedPtr์ธ ์Šค๋งˆํŠธํฌ์ธํ„ฐ๋กœ ์„ ์–ธ์ด ๋˜์–ด์žˆ๋‹ค


int main(int argc, char** argv)
{
  // ROS 2๋ฅผ initialize ํ•˜๊ฒ ๋‹ค
  rclcpp::init(argc, argv);

  // ํƒ€์ด๋จธ ์ฝœ๋ฐฑ์„ ์ด์šฉํ•˜์—ฌ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฒ ๋‹ค
  rclcpp::spin(std::make_shared<MyPublisher>());
  rclcpp::shutdown();

  return 0;
}

๋‚˜๋Š” main๋ฌธ์„ ์ฒ˜์Œ์— ๋ณด๊ณ  publisher์ธ๋ฐ ์™œ spin์ด ์žˆ์ง€ ๊ถ๊ธˆ์ฆ์„ ๊ฐ€์กŒ๋‹ค
์‚ฌ์‹ค ์—†์–ด๋„ ๋˜์ง€๋งŒ ์ •ํ™•ํ•œ ์‹œ๊ฐ„์œผ๋กœ publish ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ž์ฒด timer๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์œผ๋ฉฐ, ์ €๋ ‡๊ฒŒ ํด๋ž˜์Šค๋ฅผ ์„ ์–ธํ•  ๋•Œ๋„ ์Šค๋งˆํŠธํฌ์ธํ„ฐ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค


package.xml ์ˆ˜์ •

ํŒŒ์ผ์„ ์—ด์–ด์„œ buildtool_depend์— ament_cmake๋ผ๊ณ  ์ ํ˜€ ์žˆ๋Š” ์ค„ ๋ฐ”๋กœ ๋ฐ‘์—๋‹ค๊ฐ€ ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค

<depend>rclcpp</depend>
<depend>std_msgs</depend>

์ด์ œ ์ด ์˜์กด์„ฑ์„ CMakeLists.txt์— ๋ฐ˜์˜ํ•˜๋ฉด ๋œ๋‹ค

CMakeLists.txt ์ˆ˜์ •

ํŒŒ์ผ์„ ์—ด์–ด์„œ find_package(ament_cmake REQUIRED) ๋‹ค์Œ ์ค„์— ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค
์ด ํ”„๋กœ์ ํŠธ์˜ dependencies๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ๋Š” ๊ณผ์ •์ด๋‹ค

find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)


๋‹ค์Œ์€ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ํŒŒ์ผ์„ ๋งŒ๋“œ๋Š” ์ ˆ์ฐจ๋‹ค

add_executable(pub src/pub.cpp)
ament_target_dependencies(pub rclcpp std_msgs)


์ด ์‹คํ–‰ํŒŒ์ผ ๋ช…์„ ros 2๊ฐ€ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์ž

install(TARGETS
  pub
  DESTINATION lib/${PROJECT_NAME})

๋นŒ๋“œ ๋ฐ ์‹คํ–‰

๋ฐ‘์— ์‚ฌ์šฉ๋˜๋Š” ๋‹จ์ถ•์–ด๋Š” ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์ž

์•„๋ž˜์™€ ๊ฐ™์ด ํŒจํ‚ค์ง€ ๋นŒ๋“œ ํ›„์— ์‹คํ–‰ํ•ด๋ณธ๋‹ค

$ cbp my_ros2
$ ros2 run my_ros2 pub


์•„๋ž˜์™€ ๊ฐ™์ด ์ถœ๋ ฅ๋œ๋‹ค๋ฉด ์„ฑ๊ณต!

[INFO] [1662093558.003252577] [my_publisher]: Publish: bigbigpark! 0
[INFO] [1662093558.503316640] [my_publisher]: Publish: bigbigpark! 1
[INFO] [1662093559.003363595] [my_publisher]: Publish: bigbigpark! 2
[INFO] [1662093559.503298140] [my_publisher]: Publish: bigbigpark! 3
[INFO] [1662093560.003335839] [my_publisher]: Publish: bigbigpark! 4
[INFO] [1662093560.503317732] [my_publisher]: Publish: bigbigpark! 5
[INFO] [1662093561.003289612] [my_publisher]: Publish: bigbigpark! 6
[INFO] [1662093561.503353750] [my_publisher]: Publish: bigbigpark! 7
[INFO] [1662093562.003375748] [my_publisher]: Publish: bigbigpark! 8
[INFO] [1662093562.503328776] [my_publisher]: Publish: bigbigpark! 9
[INFO] [1662093563.003220890] [my_publisher]: Publish: bigbigpark! 10

Reference

Leave a comment