사용자 정의 인터페이스

평범한컴공생·2023년 1월 3일
0

[ROS2]

목록 보기
18/19
post-thumbnail

배경

사용자 정의 메시지 인터페이스를 만들어보았으니 인터페이스를 만들어 보자.

현재 환경에서 인터페이스는 CMake 패키지를 통해서만 구현할 수 있다. 그러나 CMake 패키지에 Python 노드나 라이브러리가 존재할 수 있다.

작업

1. 패키지 생성

워크 스페이스의 src 디렉터리에서 more_interfaces 패키지를 생성하자.

ros2 pkg create --build-type ament_cmake more_interfaces
mkdir more_interfaces/msg

2. 메시지 파일 생성

more_interfaces/msg에서 AddressBook.msg 파일을 생성하자. 메시지 파일은 다음의 코드로 구성된다.

bool FEMALE=true
bool MALE=false

string first_name
string last_name
bool gender
uint8 age
string address

메시지는 다음과 같은 필드로 구성된다.

  • first_name: string
  • last_name: string
  • gender: bool
  • age: uint8
  • address: string

FEMALE 또는 MALE과 같이 디폴트 값을 설정할 수 있다.

2.1 메시지 파일 빌드

package.xml 파일에 다음을 추가한다.

<buildtool_depend>rosidl_default_generators</buildtool_depend>

<exec_depend>rosidl_default_runtime</exec_depend>

<member_of_group>rosidl_interface_packages</member_of_group>

CMakeLists.txt에도 마찬가지로 다음을 추가한다.

find_package(rosidl_default_generators REQUIRED)

생성하고 싶은 메시지를 다음과 같이 정의할 수 있다.

set(msg_files
  "msg/AddressBook.msg"
)

.msg 파일을 직접 추가함으로써, CMake는 별도의 .msg 파일을 추가한 후 프로젝트를 재구성해야 함을 알고 있다.

다음과 같이 메시지를 생성한다.

rosidl_generate_interfaces(${PROJECT_NAME}
  ${msg_files}
)

메시지의 런타임 종속성을 위해 다음을 추가한다.

ament_export_dependencies(rosidl_default_runtime)

메시지의 소스 파일을 생성할 수 있는 준비가 되었다.

참고로 다음과 같이 여러 개의 인터페이스를 추가할 수 있다.

set(msg_files
"msg/Message1.msg"
"msg/Message2.msg"
# etc
)

set(srv_files
"srv/Service1.srv"
"srv/Service2.srv"
# etc
)
rosidl_generate_interfaces(${PROJECT_NAME}
${msg_files}
${srv_files}
)

3. 패키지 인터페이스 사용

위에서 생성하려는 메시지를 사용하는 코드를 작성해 보자.

more_interfaces/src에 아래의 코드로 된 publish_address_book.cpp파일을 작성하자.

#include <chrono>
#include <memory>

#include "rclcpp/rclcpp.hpp"
#include "more_interfaces/msg/address_book.hpp"

using namespace std::chrono_literals;

class AddressBookPublisher : public rclcpp::Node
{
public:
  AddressBookPublisher()
  : Node("address_book_publisher")
  {
    address_book_publisher_ =
      this->create_publisher<more_interfaces::msg::AddressBook>("address_book", 10);

    auto publish_msg = [this]() -> void {
        auto message = more_interfaces::msg::AddressBook();

        message.first_name = "John";
        message.last_name = "Doe";
        message.age = 30;
        message.gender = message.MALE;
        message.address = "unknown";

        std::cout << "Publishing Contact\nFirst:" << message.first_name <<
          "  Last:" << message.last_name << std::endl;

        this->address_book_publisher_->publish(message);
      };
    timer_ = this->create_wall_timer(1s, publish_msg);
  }

private:
  rclcpp::Publisher<more_interfaces::msg::AddressBook>::SharedPtr address_book_publisher_;
  rclcpp::TimerBase::SharedPtr timer_;
};


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

  return 0;
}

3.2 퍼블리셔 빌드

CMakeLists.txt에 노드의 타깃을 추가한다.

find_package(rclcpp REQUIRED)

add_executable(publish_address_book
  src/publish_address_book.cpp
)

ament_target_dependencies(publish_address_book
  "rclcpp"
)

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

3.3 인터페이스 링크

동일한 패키지에서 생성된 메시지를 사용하기 위해 CMakeLists.txt에 다음을 추가한다.

rosidl_target_interfaces(publish_address_book
  ${PROJECT_NAME} "rosidl_typesupport_cpp")

4. 빌드 및 테스트

워크 스페이스의 루트로 이동한 후 colcon으로 빌드를 수행한다.

cd ~/ros2_ws
colcon build --packages-up-to more_interfaces

이후 퍼블리셔 노드를 실행한다.

. install/local_setup.bash
ros2 run more_interfaces publish_address_book

이후 해당 터미널에서 cpp파일에 설정한 값들로 퍼블리시 되는 것을 알 수 있다.

다른 터미널을 열어 echo를 통해 메시지를 수신해 보자.

. install/setup.bash
ros2 topic echo /address_book

참고

ROS 2 Documentation: Foxy

profile
학부 연구생(220627~)

0개의 댓글