零、前情提要
主要参考 官网:Creating custom ROS 2 msg and srv files
前置文章ros2 foxy 学写简单的服务。
一、创建文件夹和包
#dev_ws可以自己命名,但最好保留`_ws`的缩写标志。
mkdir -p dev_ws/src
#进入源目录
cd dev_ws/src
#创建包
ros2 pkg create --build-type ament_cmake tutorial_interfaces
tutorial_interfaces
是新包的名称。 注意它是一个CMake
包; 目前没有办法在纯Python
包中生成.msg
或.srv
文件。 您可以在CMake
包中创建自定义接口,然后在Python
节点中使用。
进入
dev_ws/src/tutorial_interfaces
并生成.msg
和.srv
各自独立的文件夹。
cd tutorial_interfaces
mkdir msg
mkdir srv
二、创建自定义文件
在
msg
文件夹中创建Num.msg
文件,创建文件就不写了,并写入如下内容:
int64 num
在
srv
文件夹中创建AddThreeInts.srv
文件,并填入一下内容,分割线前是请求数据,分割线后是响应数据。
int64 a
int64 b
int64 c
---
int64 sum
三、修改CMakeLists.txt
修改
CMakeLists.txt
文件,里面添加如下行,注意文件路径名对应。
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/Num.msg"
"srv/AddThreeInts.srv"
)
四、修改package.xml
在文件中添加如下行,前两行是添加依赖,后面一行作用暂不清楚。
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
五、创建包
colcon build --packages-select tutorial_interfaces
成功后就可以被其他包调用了。
六、验证包
开一个新终端,在
dev_ws
下激活
. install/setup.bash
查验文件,先查
msg
文件
ros2 interface show tutorial_interfaces/msg/Num
会显示
int64 num
同理,输入
ros2 interface show tutorial_interfaces/srv/AddThreeInts
会返回
int64 a
int64 b
int64 c
---
int64 sum
七、测试
7.1用发布订阅模型测试.msg
文件
在
dev_ws/src
目录下面创建cpp_testmsg_pubsub
包
ros2 pkg create --build-type ament_cmake cpp_testmsg_pubsub
添加文件以及文件的意思之类的可以先复习下用colcon和c++写自己的第一个ROS2包。
在cpp_testmsg_pubsub/src
中添加publisher_member_function.cpp
文件如下:
#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
timer_ = this->create_wall_timer(
500ms, std::bind(&MinimalPublisher::timer_callback, this));
}
private:
void timer_callback()
{
auto message = tutorial_interfaces::msg::Num(); // CHANGE
message.num = this->count_++; // CHANGE
RCLCPP_INFO(this->get_logger(), "Publishing: '%d'", message.num); // CHANGE
publisher_->publish(message);
}
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;
}
subscriber_member_function.cpp
:
#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")
{
subscription_ = this->create_subscription<tutorial_interfaces::msg::Num>( // CHANGE
"topic", 10, std::bind(&MinimalSubscriber::topic_callback, this, _1));
}
private:
void topic_callback(const tutorial_interfaces::msg::Num::SharedPtr msg) const // CHANGE
{
RCLCPP_INFO(this->get_logger(), "I heard: '%d'", msg->num); // CHANGE
}
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;
}
CMakeList.txt
:
cmake_minimum_required(VERSION 3.5)
project(cpp_testmsg_pubsub)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
# 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 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(tutorial_interfaces REQUIRED) # CHANGE
add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp tutorial_interfaces) # CHANGE
add_executable(listener src/subscriber_member_function.cpp)
ament_target_dependencies(listener rclcpp tutorial_interfaces) # CHANGE
install(TARGETS
talker
listener
DESTINATION lib/${PROJECT_NAME})
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# uncomment the line when a copyright and license is not present in all source files
#set(ament_cmake_copyright_FOUND TRUE)
# the following line skips cpplint (only works in a git repo)
# uncomment the line when this package is not in a git repo
#set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
package.xml
:
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>cpp_testmsg_pubsub</name>
<version>0.0.0</version>
<description>TODO: Package description</description>
<maintainer email="default@default.com">default</maintainer>
<license>TODO: License declaration</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>tutorial_interfaces</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>
dev_ws
目录下命令行构建
colcon build --packages-select cpp_testmsg_pubsub
打开两个
terminal
,并分别source
和运行
. install/setup.bash
ros2 run cpp_testmsg_pubsub talker
. install/setup.bash
ros2 run cpp_testmsg_pubsub listener
最后得到如下的图
测试运行效果
7.2用服务模型测试.srv
文件
服务模型测试直接参考上一节,以及ros2 foxy 学写简单的服务和官网# Creating custom ROS 2 msg and srv files第7.2节测试吧,我懒得写了,就留个截图。
注意事项
.msg
文件和.srv
文件温家明必须首字母大写,按驼峰原则命名,会被自动扩展成.hpp
文件,扩展的文件的文件名会自动把大写转换成下划线和小写。
网友评论