https://docs.ros.org/en/jazzy/Tutorials/Beginner-Client-Libraries/Custom-ROS2-Interfaces.html
Creating custom msg and srv files — ROS 2 Documentation: Jazzy documentation
Because the interfaces rely on rosidl_default_generators for generating language-specific code, you need to declare a build tool dependency on it. rosidl_default_runtime is a runtime or execution-stage dependency, needed to be able to use the interfaces la
docs.ros.org
background
- 이전의 튜토리얼에서는 message와 service 인터페이스를 작성해보았다. 이때 사용한 인터페이스들은 미리 정의된 것 들 이었다.
- 미리 정의된 인터페이스를 사용하는 것은 좋은 습관이지만, 간혹가다가 나만의 message와 service를 정의해야할 필요가 있을때가 있다. 이번에는 사용자 정의 인터페이스 정의를 만드는 간단한 방법을 소개한다.
- ros에서 interface는 표준화된 데이터 형식을 의미
task
- 1. create a new package
- 이번에는 .msg와 .srv를 그들의 패키지에 만들어 볼것이다. 그리고 그들울 별도의 패키지에서 사용하는 방법을 배운다. 두 패키지는 같은 workspace에 존재해야한다.
- 이전 튜토리얼에서 만든 pub/sub과 service/client 패키지를 사용할것이니 해당 공간에 2개의 패키지가 존재하는지 확인하고, 아래의 명령어로 패키지를 생성하자.
- 패키지가 생성되면 해당 폴더로 들어가서 msg srv 디렉토리 2개를 만들자.

ros2 pkg create --build-type ament_cmake --license Apache-2.0 tutorial_interfaces
cd tutorial_interfaces
mkdir srv msg
- 2. 우선 msg를 정의하자.
- 2-1. msg dir에 들어가자.
- 2-2. Num.msg파일을 만들어서 int64 num문장 하나만 써주자.
- 2-3. Sphere.msg 파일을 만들어서 2개의 문장을 써주자.
cd msg
echo "int64 num" >> Num.msg
echo -e "geometry_msgs/Point center\n""float64 radius" >> Sphere.msg
- 3. srv정의하자
- 2-1. srv dir에 들어가자.
- 2-2. AddTreeInts.srv파일을 만들자.
echo -e "int64 a\nint64 b\nint64 c\n---\nint64 sum" >> AddThreeInts.srv
- 4. CMakeList.txt를 수정
find_package(geometry_msgs REQUIED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Num.msg"
"msg/Sphere.msg"
"srv/AddThreeInts.srv"
DEPENDENCIES geometry_msgs
)

- 5. package.xml도 수정하자.
- 이를 수정하는 이유는 interfaces가 rosidl_default_generators에게 의존한다. 그래서 need to declare a build tool dependency on it.
<depend>geometry_msgs</depend>
<buildtool_depend>rosidl_default_generators</buildtool_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
6. 빌드
colcon build --packages-select tutorial_interfaces
7. source하기
source install/setup.bash
8. 확인 하기
ros2 interface show tutorial_interfaces/msg/Num
ros2 interface show tutorial_interfaces/msg/Sphere
ros2 interface show tutorial_interfaces/srv/AddThreeInts

9. cpp_pubsub패키지로 가서 publisher와 subscriber를 수정하자.
#include <chrono>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "tutorial_interfaces/msg/num.hpp" // CHANGE
using namespace std::chrono_literals;
class MinimalPublisher : public rclcpp::Node
{
public:
MinimalPublisher()
: Node("minimal_publisher"), count_(0)
{
publisher_ = this->create_publisher<tutorial_interfaces::msg::Num>("topic", 10); // CHANGE
auto timer_callback = [this](){
auto message = tutorial_interfaces::msg::Num(); // CHANGE
message.num = this->count_++; // CHANGE
RCLCPP_INFO_STREAM(this->get_logger(), "Publishing: '" << message.num << "'"); // CHANGE
publisher_->publish(message);
};
timer_ = this->create_wall_timer(500ms, timer_callback);
}
private:
rclcpp::TimerBase::SharedPtr timer_;
rclcpp::Publisher<tutorial_interfaces::msg::Num>::SharedPtr publisher_; // CHANGE
size_t count_;
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalPublisher>());
rclcpp::shutdown();
return 0;
}
#include <functional>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "tutorial_interfaces/msg/num.hpp" // CHANGE
using std::placeholders::_1;
class MinimalSubscriber : public rclcpp::Node
{
public:
MinimalSubscriber()
: Node("minimal_subscriber")
{
auto topic_callback = [this](const tutorial_interfaces::msg::Num & msg){ // CHANGE
RCLCPP_INFO_STREAM(this->get_logger(), "I heard: '" << msg.num << "'"); // CHANGE
};
subscription_ = this->create_subscription<tutorial_interfaces::msg::Num>( // CHANGE
"topic", 10, topic_callback);
}
private:
rclcpp::Subscription<tutorial_interfaces::msg::Num>::SharedPtr subscription_; // CHANGE
};
int main(int argc, char * argv[])
{
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<MinimalSubscriber>());
rclcpp::shutdown();
return 0;
}
- 10. CMakelist도 수정
cmake_minimum_required(VERSION 3.8)
project(cpp_pubsub)
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)
find_package(tutorial_interfaces REQUIRED)
add_executable(talker src/publisher_lambda_function.cpp)
# ament_target_dependencies(talker rclcpp std_msgs)
ament_target_dependencies(talker rclcpp tutorial_interfaces)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
set(ament_cmake_copyright_FOUND TRUE)
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
add_executable(listener src/subscriber_lambda_function.cpp)
# ament_target_dependencies(listener rclcpp std_msgs)
ament_target_dependencies(listener rclcpp tutorial_interfaces)
install(TARGETS
talker
listener
DESTINATION lib/${PROJECT_NAME})
ament_package()
- 11. package.xml에는 다음 라인을 추가하자.
- <depend>tutorial_interfaces</depend>
- 12. pubsub 빌드
- colcon build --packages-select cpp_pubsub
- colcon build --packages-select cpp_pubsub
- 13. 다시 소스
source install/setup.bash
- 14. 터미널 2개로 확인
ros2 run cpp_pubsub talker
ros2 run cpp_pubsub listener

- 15. 위에서 publisher subscriber를 수정한것처럼 server와 client도 수정
- 16. Cmake , package 두개 수정
- 15번16번은 링크가서 확인
- 17. colcon build --packages-select cpp_srvcli 입력
- 18. 소스 다시 하기
- 19. 실행해서 결과 확인

'ROS 2' 카테고리의 다른 글
| ros2 lifecycle이란? (0) | 2025.03.24 |
|---|---|
| ROS2에서 TF란? (0) | 2025.03.14 |
| gazebo tutlebot4 카메라 보기 (0) | 2025.02.24 |
| ROS2 turtlebot4을 gazebo sim에 띄워보기 (0) | 2025.02.23 |
| Launch file (0) | 2025.02.05 |