[ROS2] (14)-C++로 퍼블리셔와 서브스크라이버 만들기
퍼블리셔와 서브스크라이버 만들기
이번 포스팅에서는 토픽을 통해 정보를 전달하는 간단한 “talker”, “listner” 시스템을 만들어볼 것이다.
패키지 만들기
먼저, dev_ws
폴더에 cpp_pubsub
이라는 새로운 패키지를 만든다.
$ cd ~/dev_ws/src
$ ros2 pkg create --build-type ament_cmake cpp_pubsub
퍼블리셔 노드 작성하기
dev_ws/src/cpp_pubsub/src
폴더에 아래의 예제 코드를 다운로드 받는다.
$ wget -O publisher_member_function.cpp https://raw.githubusercontent.com/ros2/examples/foxy/rclcpp/topics/minimal_publisher/member_function.cpp
dev_ws/src/cpp_pubsub/src
폴더에 publisher_member_function.cpp
라는 파일이 다운로드 받아졌다. 이 파일을 열어서 코드를 확인해보자.
#include <chrono>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
using namespace std::chrono_literals;
먼저, 필요한 헤더파일을 포함시키고 있다. 여기서 rclcpp/rclcpp.hpp
는 ROS2 시스템을 사용할 수 있게 해주는 헤더이고, std_msgs/msg/string.hpp
는 데이터를 퍼블리시할 때 사용하는 메시지 타입을 포함하고 있는 헤더이다. 여기에 포함된 헤더들은 package.xml
, CMakeLists.txt
파일에 추가되어야 한다.
class MinimalPublisher : public rclcpp::Node
노드 클래스인 MinimalPublisher
를 rclcpp::Node
로부터 상속받아서 생성하고 있다. 코드에서 this
라고 하는 것은 모두 이 노드를 의미한다.
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));
}
생성자에서 노드 이름을 minimal_publisher
로, count_
를 0으로 초기화하고 있다. 생성자 내부에서는 publisher
가 String
메시지 타입, topic
이라는 이름의 토픽, 10
의 queue 사이즈로 초기화되었다. timer_
도 역시 초기화 되었다.
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);
}
timer_callback
함수가 메세지가 설정되고, 실제로 퍼블리시 되는 곳이다. RCLCPP_INFO
는 퍼블리시되는 모든 메시지를 콘솔창에 출력해준다.
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;
}
rclcpp::init
은 ROS2를 시작시켜주고, rclcpp::spin
은 노드로부터 데이터를 처리하는 것을 시작하는 것이다.
퍼블리셔 노드 dependency 추가하기
dev_ws/src/cpp_pubsub
폴더에서 package.xml
파일을 열어서 dependency를 추가해보자.
$ cd ~/dev_ws/src/cpp_pubsub
$ gedit package.xml
아래와 같이 buildtool dependency 아래에 2가지 dependency를 추가해준다.
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
이제 dev_ws/src/cpp_pubsub
폴더에서 CMakeLists.txt
파일을 열어보자. 마찬가지로 아래와 같이 dependency 부분에 2줄을 추가해준다.
# find dependencies
find_package(ament_cmake REQUIRED)
# uncomment the following section in order to fill in
# further dependencies manually.
# find_package(<dependency> REQUIRED)
find_package(rclcpp REQUIRED)
find_package(str_msgs REQUIRED)
이제 아래와 같이 talker
라는 이름의 실행파일을 만드는 부분도도 추가해준다.
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)
마지막으로 ros2 run
이 실행파일을 찾을 수 있도록 아래의 내용도 추가해준다.
install(TARGETS
talker
DESTINATION lib/${PROJECT_NAME})
이제 퍼블리셔 노드는 완성되었다. 서브스크라이브 노드도 비슷한 방법으로 만들어보자.
서브스크라이브 노드 작성하기
퍼블리셔 노드와 유사하게 예제 코드를 다운로드하자.
$ cd ~/dev_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
역시 간단하게 코드 내용을 분석해보자.
public:
MinimalSubscriber()
: Node("minimal_subscriber")
{
subscription_ = this->create_subscription<std_msgs::msg::String>(
"topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
}
대부분 퍼블리셔 노드와 유사하고, 다만 서브스크라이브 노드는 timer
가 없다. 왜냐하면 서브스크라이브 노드는 단순히 토픽이 퍼블리시될 때에만 응답하면 되기 때문이다.
서브스크라이브 노드는 퍼블리셔 노드와 의존성이 동일하기 때문에 package.xml
파일에 추가할 내용은 없다. CMakeLists.txt
파일에만 아래와 같이 실행파일을 만드는 부분을 추가하자. install()
에는 기존에 적혀있던 내용에 더하여 listener
만 한 줄 추가해주면 된다.
add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp std_msgs)
install(TARGETS
talker
listener
DESTINATION lib/${PROJECT_NAME})
노드 빌드 및 실행하기
먼저, 빌드하기 전에 workspace에 모든 dependency가 있는지 확인해보자.
$ cd ~/dev_ws
$ rosdep install -i --from-path src --rosdistro foxy -y
이제 cpp_pubsub
패키지만 빌드해보자.
$ cd ~/dev_ws
$ colcon build --packages-select cpp_pubsub
설정파일을 source 하고 talker
노드를 실행해보자.
$ cd ~/dev_ws
$ source install/setup.bash
$ ros2 run cpp_pubsub talker
터미널 창에 메시지를 출력하는 것을 확인할 수 있다. 이제 listener
노드도 실행해보자.
$ cd ~/dev_ws
$ source install/setup.bash
$ ros2 run cpp_pubsub listener
talker
노드에서 퍼블리시한 토픽을 listener
노드에서 수신하는 것을 확인할 수 있다.
댓글남기기