[c++] ros2 pub / sub

About_work·2024년 9월 4일
0

c++

목록 보기
7/8

1. ros2 공식 문서

C++로 간단한 퍼블리셔와 서브스크라이버 작성하기

목표: C++를 사용하여 퍼블리셔와 서브스크라이버 노드를 생성하고 실행합니다.

작업 내용

1. 패키지 생성

  • 새 터미널을 열고 ROS 2 설치 경로를 소스하여 ros2 명령이 동작하도록 합니다.
  • 이전 튜토리얼에서 생성한 ros2_ws 디렉토리로 이동합니다.
  • 패키지는 워크스페이스의 루트가 아닌 src 디렉토리 안에서 생성해야 하므로,
    • ros2_ws/src로 이동하여 패키지 생성 명령을 실행:
ros2 pkg create --build-type ament_cmake cpp_pubsub
  • 터미널에 cpp_pubsub 패키지와 그에 필요한 파일 및 폴더가 생성되었다는 메시지가 표시
  • ros2_ws/src/cpp_pubsub/src 디렉토리로 이동
    • 이 디렉토리는 모든 CMake 패키지의 소스 파일이 속해야 하는 위치

2. 퍼블리셔 노드 작성

다음 명령을 입력하여 예제 발신자 코드를 다운로드합니다:

wget -O publisher_member_function.cpp https://raw.githubusercontent.com/ros2/examples/foxy/rclcpp/topics/minimal_publisher/member_function.cpp

이제 publisher_member_function.cpp라는 새 파일이 생성됩니다. 선호하는 텍스트 편집기로 파일을 엽니다.

// 표준 C++ 헤더
#include <chrono>
#include <functional>
#include <memory>
#include <string>

// ROS 2 시스템의 주요 구성 요소들을 사용할 수 있도록 
#include "rclcpp/rclcpp.hpp"

// 데이터를 퍼블리시하는 데 사용할 내장 메시지 타입
#include "std_msgs/msg/string.hpp"

using namespace std::chrono_literals;

// 위 줄들은 노드의 종속성을 나타냅니다. 
// 종속성은 `package.xml`과 `CMakeLists.txt`에 추가해야 하며, 이는 다음 섹션에서 수행할 것입니다.

// `rclcpp::Node`를 상속하여 노드 클래스를 생성하는 코드
// 코드 내에서 `this`는 모두 노드를 참조

class MinimalPublisher : public rclcpp::Node
{
  public:
    MinimalPublisher()
    : Node("minimal_publisher"), count_(0)
    {
      publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
      timer_ = this->create_wall_timer(
      500ms, std::bind(&MinimalPublisher::timer_callback, this));
    }

  private:
    void timer_callback()
    {
      auto message = std_msgs::msg::String();
      message.data = "Hello, world! " + std::to_string(count_++);
      RCLCPP_INFO(this->get_logger(), "Publishing: '%s'", message.data.c_str());
      publisher_->publish(message);
    }
    rclcpp::TimerBase::SharedPtr timer_;
    rclcpp::Publisher<std_msgs::msg::String>::SharedPtr publisher_;
    size_t count_;
};

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

2.1 종속성 추가

  • ros2_ws/src/cpp_pubsub 디렉토리로 이동하여,
    • CMakeLists.txtpackage.xml 파일을 찾음
  • package.xml 파일을 텍스트 편집기로 엽니다.
    • 이전 튜토리얼에서 설명한 것처럼, <description>, <maintainer>, <license> 태그를 채워야 합니다:
<description>Examples of minimal publisher/subscriber using rclcpp</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>
  • ament_cmake 빌드 도구 종속성 아래에 다음 종속성을 추가합니다.
    • 이는 노드의 include 문과 일치 :
<depend>rclcpp</depend>
<depend>std_msgs</depend>
  • 이는 패키지가 빌드 및 실행될 때 rclcppstd_msgs가 필요함을 선언합니다.

2.3 CMakeLists.txt

이제 CMakeLists.txt 파일을 엽니다.

  • 기존 find_package(ament_cmake REQUIRED) 아래에 다음 줄을 추가
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)
  • 그런 다음, 실행 파일을 추가하고 talker로 이름을 지정하여
    • ros2 run 명령을 사용해 노드를 실행할 수 있게 합니다:
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
  • 마지막으로, ros2 run이 실행 파일을 찾을 수 있도록
    • install(TARGETS...) 섹션을 추가
install(TARGETS
  talker
  DESTINATION lib/${PROJECT_NAME})

CMakeLists.txt 파일을 불필요한 섹션과 주석을 제거하여 정리하면 다음과 같이 됩니다:

cmake_minimum_required(VERSION 3.5)
project(cpp_pubsub)

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(std_msgs REQUIRED)

add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)

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

ament_package()

3. 서브스크라이버 노드 작성

  • ros2_ws/src/cpp_pubsub/src로 돌아가서 다음 노드를 생성합니다. 터미널에 다음 코드를 입력합니다:
wget -O subscriber_member_function.cpp https://raw.githubusercontent.com/ros2/examples/foxy/rclcpp/topics/minimal_subscriber/member_function.cpp
  • ls 명령을 실행하면 이제 다음과 같은 결과가 출력됩니다:
publisher_member_function.cpp  subscriber_member_function.cpp
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using std::placeholders::_1;

class MinimalSubscriber : public rclcpp::Node
{
  public:
    MinimalSubscriber()
    : Node("minimal_subscriber")
    {
      subscription_ = this->create_subscription<std_msgs::msg::String>(
      "topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
    }

  private:
    void topic_callback(const std_msgs::msg::String::SharedPtr msg) const
    {
      RCLCPP_INFO(this->get_logger(), "I heard: '%s'", msg->data.c_str());
    }
    rclcpp::Subscription<std_msgs::msg::String>::SharedPtr subscription_;
};

int main(int argc, char * argv[])
{
  rclcpp::init(argc, argv);
  rclcpp::spin(std::make_shared<MinimalSubscriber>());
  rclcpp::shutdown();
  return 0;
}
  • 이 노드는 퍼블리셔와 동일한 종속성을 가지고 있으므로 package.xml에 추가할 새로운 항목은 없습니다.

3.2 CMakeLists.txt

CMakeLists.txt를 다시 열어 퍼블리셔 항목 아래에

  • 서브스크라이버 노드의 실행 파일 및 타겟을 추가
add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs)

install(TARGETS
  talker
  listener
  DESTINATION lib/${PROJECT_NAME})

4. 빌드 및 실행

  • ROS 2 시스템의 일부로 rclcppstd_msgs 패키지가 이미 설치되어 있을 가능성이 높습니다.
  • 빌드하기 전에 워크스페이스의 루트(ros2_ws)에서 rosdep을 실행하여 누락된 종속성을 확인하는 것이 좋습니다:
rosdep install -i --from-path src --rosdistro foxy -y
  • 여전히 워크스페이스의 루트(ros2_ws)에 있는 상태에서 새 패키지를 빌드합니다:
colcon build --packages-select cpp_pubsub
  • 새 터미널을 열어 ros2_ws로 이동하고, 설정 파일을 소스합니다:
. install/setup.bash
  • 이제 발신자(talker) 노드를 실행합니다:
ros2 run cpp_pubsub talker

다른 터미널을 열어 ros2_ws에서 다시 설정 파일을 소스한 후, 수신자(listener) 노드를 시작합니다:

ros2 run cpp_pubsub listener
profile
새로운 것이 들어오면 이미 있는 것과 충돌을 시도하라.

0개의 댓글