关键词:
概要:这篇主要进一步介绍ros2接口.
环境:ubuntu20.04,ros2-foxy,vscode
最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.
2.2.8拓展ros2
接口(原文:https://docs.ros.org/en/foxy/Tutorials/Single-Package-Define-And-Use-Interface.html
)
>>
教程>>
拓展ros2接口
你正阅读的是ros2
较老版本(Foxy
),但仍然支持的说明文档.想查看最新版本的信息,请看galactic版本链接( https://docs.ros.org/en/galactic/Tutorials.html
)
详述ros2接口
目标:学习更多的方法来使用自定义ros2接口
课程等级:初级
时长:15min
目录
1.背景
2.预备知识
3.步骤
3.1创建一个包
3.2创建一个msg文件
3.3使用同一个包的同一个接口
3.4测试
3.5(额外的)使用现有的接口定义
4.总结
5.下一步
6.相关内容
1.背景
前面课程中,你学了怎样创建定制化msg
和srv
接口.
虽然在专用接口包里面声明接口是最佳的,但有时声明,创建和使用接口都在同一包里面(进行)是(更)方便的.
之前说过,接口当前只能定义在CMake
包里面.然而,(使用ament_cmake_python
的话)pyhon
库和节点是有可能在CMake
包里面的,所以在一个包里面一起定义python
节点和接口是可行的.简单起见,这里使用的是cmake
包和c++
节点.
课程这里专注于msg
类型接口,但是这些步骤适用于所有类型接口的.
2.预备知识
假设在开始本课程前,你温习了前面创建自定义msg
和srv
文件课程的基础部分.
你应该安装了ros2
,有了工作空间,并且懂得包的创建.
老规矩,新开终端别忘了source
一下ros2
环境变量.
3.步骤
3.1创建一个包
在你的工作空间src目录线,创建一个名为more_interfaces
包,也里面创建一个文件夹放msg
文件:
ros2 pkg create --build-type ament_cmake more_interfaces
mkdir more_interfaces/msg
3.2创建一个msg文件
在 more_interfaces/msg
基础上,创建新文件AddressBook.msg
.
复制下面代码去创建一个消息(类型),其表示的是一个人的信息:
bool FEMALE=true
bool MALE=false
string first_name
string last_name
bool gender
uint8 age
string address
信息由5个部分组成:
姓:字符串类型
名:字符串类型
性别:布尔类型,不是男就是女
年龄:unit8类型
地址:字符串类型
注意,有些地方是可以设置默认参数的.看这里(https://docs.ros.org/en/foxy/Concepts/About-ROS-Interfaces.html#interfaceconcept
),你可以找到很多方式来自定义接口.
接着,我们需要确认msg
文件是可以用到c++
,python
或者其他语言的源码的.
3.2.1创建一个msg文件
打开文件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>
注意,编译时候,我们需要rosidl_default_generators
;运行时候,我们只需要rosidl_default_runtime
.
打开CMakeLists.txt
,添加下面几行:
找到那个包,可以将msg/srv
文件生成消息类型:
find_package(rosidl_default_generators REQUIRED)
声明你想要生成消息类型列表:
set(msg_files
"msg/AddressBook.msg"
)
手动添加.msg
文件,我们确保cmake
可以找得到,当你添加了其他.msg
文件之后,cmake
一定会重置系统配置.
生成消息:
rosidl_generate_interfaces($PROJECT_NAME
$msg_files
)
也要保证你导出信息运行时的依赖:
ament_export_dependencies(rosidl_default_runtime)
现在,你可以用自定义msg文件来生成一个源文件.当完成上面四步,我们直接跳过编译步骤.
3.2.2(特别)设置多个接口
注意:
你可以使用set来简洁列出接口:
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.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.3.1代码解析
#include "more_interfaces/msg/address_book.hpp"
包含新创建的AddressBook.msg
头文件
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");
创建一个节点和AddressBook
发布器:
auto publish_msg = [this]() -> void
创建一个回调来周期性发布消息:
auto message = more_interfaces::msg::AddressBook();
创建我们后面发布的AddressBook
消息:
message.first_name = "John";
message.last_name = "Doe";
message.age = 30;
message.gender = message.MALE;
message.address = "unknown";
输出AddressBook
每项内容:
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);
创建1
秒的定时器来实现每秒调用一次publish_msg
函数.
3.3.2编译发布者
在CMakeLists.txt
文件中,我们需要为这个节点创建新target
:
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.3连接指定的接口
为了在同一个包里面使用生成的消息类型,我们需要使用一下CMake
代码:
rosidl_target_interfaces(publish_address_book
$PROJECT_NAME "rosidl_typesupport_cpp")
这会找到用到AddressBook.msg
编写的相关c++
代码,让你target
针对性连接它.
你可能会发现,当使用的接口是来自别的包里面的,这一步是没有必要的.当我们使用的接口来同一个包(操作包和接口包属于同一个时),这个CMake
代码才是必要的.
3.4测试
返回工作空间的根目录,编译这个包:
linux:
cd ~/dev_ws
colcon build --packages-up-to more_interfaces
然后source
一下工作空间(环境变量),运行发布器:
linux:
. install/local_setup.bash
ros2 run more_interfaces publish_address_book
我们这次不创建侦听器,但是你可以尝试写一个练习一下(参考 编写简单发布器和侦听器(c++)课程)
3.5(特别)使用现有的接口定义
注意:
你可以将一个现有的定义接口用于新接口定义.例如,我们看这里,一个消息类型为Contact.msg
,它就是属于ros2
包里面的rosidl_tutorials_msgs
,假设它的定义等同于前面自定义的AddressBook.msg
接口.
在这种情况下,你已经定义了AddressBook.msg
(接口和你节点在同一个包里面)作为类型Contact
(接口和操作节点的包不相同),像这样子:
rosidl_tutorials_msgs/Contact[] address_book
为了生成这个消息(类型),你应该在Contact.msg
包里面的package.xml
文件声明依赖,rosidl_tutorials_msgs
:
<build_depend>rosidl_tutorials_msgs</build_depend>
<exec_depend>rosidl_tutorials_msgs</exec_depend>
在CMakeLists.txt
文件添加:
find_package(rosidl_tutorials_msgs REQUIRED)
rosidl_generate_interfaces($PROJECT_NAME
$msg_files
DEPENDENCIES rosidl_tutorials_msgs
)
为了能够把contacts
加到你的address_book
发布器节点里面,你要添加Contact.msg
头文件.
#include "rosidl_tutorials_msgs/msg/contact.hpp"
你在回调部分更改一些内容,像这样子:
auto publish_msg = [this]() -> void
auto msg = std::make_shared<more_interfaces::msg::AddressBook>();
rosidl_tutorials_msgs::msg::Contact contact;
contact.first_name = "John";
contact.last_name = "Doe";
contact.age = 30;
contact.gender = contact.MALE;
contact.address = "unknown";
msg->address_book.push_back(contact);
rosidl_tutorials_msgs::msg::Contact contact;
contact.first_name = "Jane";
contact.last_name = "Doe";
contact.age = 20;
contact.gender = contact.FEMALE;
contact.address = "unknown";
msg->address_book.push_back(contact);
std::cout << "Publishing address book:" << std::endl;
for (auto contact : msg->address_book)
std::cout << "First:" << contact.first_name << " Last:" << contact.last_name <<
std::endl;
address_book_publisher_->publish(*msg);
;
编译和运行更改后(的源码),会表现出所预期的消息类型msg
,和上面所定义的消息msg
阵列.
4.总结
在本课程,你尝试了不同方式来定义接口,然后(练习了)构建一个接口和其被使用都在同一包进行的方式.
你也应该学习如何使用另外一个接口作为一个类型,package.xml, CMakeLists.txt,
和#include
声明(如何写)来使用(该接口功能)也是很必要的.
5.下一步
下面,你会创建一个简单的ros2
包,会学习launch
文件里面定制化参数如何设置.当然,你可以选择c++或者python来写它(包源文件).
6.相关内容
这里有几个设计文档(https://design.ros2.org/#interfaces
)关于ros2
接口和idl
(接口定义语言)的.
其他
个人认为重点:
同一包,接口定义和调用的实现,包内文件配置方式;
将其他现有的接口作为新接口时,包内文件配置方式
****************
个人碰到问题:自定义msg
是无法生成头文件的,缘由未知;由于前面编译通过不了,后面的使用现有接口定义文件练习这些也是没有实操的.
报错理由是cmake出错了,也就是CMakeLists.txt
文件里面下面语句有问题:
rosidl_target_interfaces(publish_address_book
$PROJECT_NAME "rosidl_typesupport_cpp")
编译报错窗口提示:
CMake Error at /opt/ros/foxy/share/rosidl_cmake/cmake/rosidl_target_interfaces.cmake:40 (message):
rosidl_target_interfaces() the second argument 'more_interfaces' must be a
valid target name
Call Stack (most recent call first):
CMakeLists.txt:31 (rosidl_target_interfaces)
目前还没有解决这个问题,有小伙伴知道的话,麻烦留言告知一下哈,多谢了.
*****************
这课程是在等毕业证那十几天搞的,室友问,现在在线翻译这么强大,为啥还在这里瞎折腾呢?我说,我的目地是好好认真看一下,了解一下,自己折腾,目前是我想到最好的办法来获得最佳效果,即使这翻译有点别扭,哈哈哈.
#####################
不积硅步,无以至千里
好记性不如烂笔头
感觉有点收获的话,麻烦大大们点赞收藏哈
ros2学习笔记18-velodyne16雷达点云在ros2中可视化案例参考(代码片段)
环境:ubuntu20.04,ros-foxy,vscode,velodyne-16背景:练习如何将velodyne-16雷达点云数据在ros2中读取并可视化.折腾了很久,并没有找到类似案例,所以自己总结一下.1.修改电脑ip这里修改自己电脑ip,跟大多数... 查看详情
ros2学习笔记12--创建ros2包(代码片段)
概要:这篇主要介绍如何创建ros2包环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.2.2创建自己第一个ros2包(原文:https://docs.ros.org/en/foxy/Tutor... 查看详情
ros2学习笔记25--ros2话题统计编写教程(c++)(代码片段)
概要:这篇内容主要介绍用c++编写能够统计话题的侦听器环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现4.1ros2话题统计教程(C++)(... 查看详情
ros2学习笔记19--探索ros2doctor工具(代码片段)
概要:这篇主要介绍ros2doctor工具环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.2.11探索ros2doctor工具(原文:https://docs.ros.org/en/foxy/Tutorials/Get... 查看详情
ros2学习笔记10--使用ros2bag进行录制和回放数据(代码片段)
概要:这篇主要介绍使用ros2bag进行录制和回放数据环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.1.10录制和回放数据(原文:https://docs.ros.or... 查看详情
ros2学习笔记28--ros2环境下,多激光雷达启动的launch文件编写样式参考(代码片段)
背景:一次需要读取多个velodyne的雷达点云数据,但是ros2知识缺少,一番折腾终有成果.1.准备velodyne的ros2版本驱动链接:https://github.com/ros-drivers/velodyne/tree/ros22.launch文件编写2.1官方 查看详情
ros2学习笔记29--项目从ros1迁移到ros2的经验参考(代码片段)
环境:ubuntu20.04,ros-foxy(ros2),vscode背景:项目需要,一直折腾把ros1下面的包升级到ros2版本.以下纯属个人查找资料摸索,自我理解所得,有错误的地方,望大佬们不吝赐教.1.消失的句柄ro... 查看详情
ros2学习笔记20--创建一个action(代码片段)
概要:这篇内容主要介绍如何创建一个action环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.3.1创建一个动作(原文:https://docs.ros.org/en/foxy/Tutori... 查看详情
ros2学习笔记11--工作空间的创建(代码片段)
概要:这篇主要介绍工作空间的创建环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.2.1创建工作空间(原文:https://docs.ros.org/en/foxy/Tutorials/Wor... 查看详情
ros2学习笔记9--创建一个launch文件(代码片段)
概要:这篇主要介绍launch文件环境:ubuntu20.04,ros2-foxy,vscode最后没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.1.9创建一个launch文件(原文:https://docs.ros.org/en/foxy/Tutorials/Launch-Files... 查看详情
ros2学习笔记24--用colcon对包进行编译(代码片段)
概要:这篇内容主要介绍用colcon对包进行编译环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现3.6用colcon对包进行编译(原文:https://docs.ros.org/en/foxy/Tu... 查看详情
ros2学习笔记27--实现自定义内存分配器(代码片段)
概要:这篇内容主要介绍如何实现自定义内存分配器环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现4.3实现自定义内存分配器(原文:https://docs.ros.or... 查看详情
ros2学习笔记17--在类中使用参数(c++)(代码片段)
概要:这篇主要介绍在类中使用参数(C++)环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.2.9在类中使用参数(C++)(... 查看详情
ros2学习笔记22--使用launch启动/监听多个node节点(代码片段)
概要:这篇内容主要介绍如何使用launch启动/监听多个node节点环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现3.4使用launch启动/监听多个node节点ÿ... 查看详情
ros2学习笔记23--将多个node节点组合到单一进程中(代码片段)
概要:这篇内容主要介绍将多个node节点组合到单一进程中环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现3.5多个node节点组合到单一进程中(原文:ht... 查看详情
ros2学习笔记26--使用快速dds查找服务作为查找协议(社区贡献)(代码片段)
概要:这篇内容主要介绍使用快速DDS查找服务作为查找协议(社区贡献)环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现4.2使用快速DDS查找服务作为... 查看详情
ros2学习笔记21--编写action服务器和客户端(c++)(代码片段)
概要:这篇内容主要介绍如何使用C++来编写动作服务器和客户端环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.3.2编写动作服务器和客户端(... 查看详情
ros2学习笔记13--编写一个简单的发布器和侦听器(c++)(代码片段)
概要:这篇主要介绍编写发布器和侦听器的简单套路(C++)环境:ubuntu20.04,ros2-foxy,vscode最后如果没有陈述实操过程中碰到问题的话,则表示该章节都可被本人正常复现.2.2.3编写一个简单的发布器和... 查看详情