适合有ROS1基础的宝宝们~,参考文献:第1章 ROS2概述与环境搭建 · GitBook、鱼香ROS:《ROS2机器人开发:入门与实践》
写在前面:
- ROS2中通信机制跟ROS1还是差不多的:话题/服务/动作通信,通信的数据载体,称为"接口"(msg、srv、action文件)
- ROS2中没有master主节点概念,同时将基于TCP/UDP的通信协议替换成DDS
- ROS2分布式通讯中,需要设置相同的DOMAIN_ID ,DDS,以及允许跨机通信
- 在ROS2中大部分封装采用面向对象特征,需要稍微复习一下面向对象
1.安装ROS2
1.1 鱼香ROS一键安装
wget http://fishros.com/install -O fishros && . fishros小鱼的一键安装系列 | 鱼香ROShttps://fishros.org.cn/forum/topic/20/%E5%B0%8F%E9%B1%BC%E7%9A%84%E4%B8%80%E9%94%AE%E5%AE%89%E8%A3%85%E7%B3%BB%E5%88%97
1.2 构建系统与构建工具
两者的区分点在于针对的对象不同,构建系统只针对一个单独的包进行构建,而构建工具重点在于按照依赖关系依次调用构建系统完成一系列功能包的构建。
| ROS中用到的构建系统: | CMake, ament_cmake, catkin, Python setuptools. |
| ROS中用到的构建工具: | colcon、catkin_make、catkin_make_isolated、catkin_tools。 |
colcon作为构建工具,通过调用CMake, Python setuptools完成构建。
- 构建过程中,colcon会按照依赖关系按顺序对功能包进行编译安装,所有依赖都是从环境变量或本地路径进行查找,不允许路径中出现两个同名的功能包。
- 若在构建过程中,没有找到相应的功能包,colcon不会报错,而会继续构建。
1.3 构建工具Colcon安装
sudo apt install python3-colcon-common-extensions1.4 工作空间及编译流程
mkdir -p ws_alina/src #创建工作空间以及子级目录 src,工作空间名称可以自定义 cd ws_alina #进入工作空间 colcon build #编译工作空间目录结构
WorkSpace --- 自定义的工作空间。 |--- build:存储中间文件的目录,该目录下会为每一个功能包创建一个单独子目录。 |--- install:安装目录,该目录下会为每一个功能包创建一个单独子目录。 |--- log:日志目录,用于存储日志文件。 |--- src:用于存储功能包源码的目录。 |-- C++功能包 |-- package.xml:包信息,比如:包名、版本、作者、依赖项。 |-- CMakeLists.txt:配置编译规则,比如源文件、依赖项、目标文件。 |-- src:C++源文件目录。 |-- include:头文件目录。 |-- msg:消息接口文件目录。 |-- srv:服务接口文件目录。 |-- action:动作接口文件目录。 |-- Python功能包 |-- package.xml:包信息,比如:包名、版本、作者、依赖项。 |-- setup.py:与C++功能包的CMakeLists.txt类似。 |-- setup.cfg:功能包基本配置文件。 |-- resource:资源目录。 |-- test:存储测试相关文件。 |-- 功能包同名目录:Python源文件目录。相比catkin,colcon少了devel目录:
bulid存储中间文件的目录,该目录下会为每一个功能包创建一个单独子目录。install安装目录,该目录下会为每一个功能包创建一个单独子目录。log日志目录,用于存储日志文件。
colcon build 参数
[可选参数]
| 参数 | 作用 | 可选值 |
|---|---|---|
--symlink-install | 使用符号链接代替复制文件。(开发中比较常用) | 无 |
| --cmake-args | 向基于CMake的包传递参数。 | -DCMAKE_BUILD_TYPE=Debug / Release |
--packages-select pkg1 pkg2 #仅生成单个包(或选定的包) --packages-ignore pkg1 pkg2 #忽略构建选定的包 --packages-up-to my_pkg #构建选定的包,包括其依赖项 --packages-above #整个工作区,然后对其中一个包进行了更改。此指令将重构此包,以及(递归地)重构依赖于此包的所有包colcon构建工具 - sgqmax - 博客园https://www.cnblogs.com/sgqmax/p/18521144
1.5 功能包创建
cd ~/ros2_ws/src ros2 pkg create [可选参数] <功能包名称> # 创建C++包 ros2 pkg create --build-type ament_cmake <package_name> # 或创建Python包 ros2 pkg create --build-type ament_python <package_name> #示例 ros2 pkg create cpp_demo --build-type ament_cmake --dependencies rclcpp std_msgs --license Apache-2.0[可选参数]
| 参数 | 作用 | 可选值 |
|---|---|---|
--build-type | 指定构建系统类型 | ament_cmake(C++)、ament_python(Python)、cmake(传统CMake) |
--dependencies | 声明依赖的ROS2包(空格分隔多个依赖) | 如rclcpp、rclpy、std_msgs等 |
--license | 指定开源许可证 | Apache-2.0、MIT、BSD等 |
--help | 显示该命令的所有参数说明及使用方法 | 无 |
1.6 常用命令
这些命令往往可以结合grep来查找~
| 分类 | 命令 | 说明 | 示例 |
|---|---|---|---|
| 节点 | ros2 node list | 列出所有运行中的节点 | ros2 node list |
ros2 node info <node_name> | 查看节点的详细信息(订阅/发布的话题、服务等) | ros2 node info /turtlesim | |
| 话题 | ros2 topic list | 列出所有活动的话题 | ros2 topic list -t(同时显示类型) |
ros2 topic echo <topic_name> | 实时打印话题上的消息 | ros2 topic echo /turtle1/cmd_vel | |
ros2 topic info <topic_name> | 查看话题的类型、发布者/订阅者数量 | ros2 topic info /turtle1/pose | |
ros2 topic info <topic_name>--verbose | 查看话题的类型、发布者/订阅者详细信息 | ros2 topic info /turtle1/pose--verbose | |
ros2 topic pub <topic_name> <msg_type> <data> | 手动发布消息到话题 | ros2 topic pub /turtle1/cmd_vel geometry_msgs/Twist "{linear: {x: 1.0}}" | |
ros2 topic hz <topic_name> | 统计话题的发布频率 | ros2 topic hz /turtle1/pose | |
ros2 topic bw <topic_name> | 估算话题的带宽 | ros2 topic bw /camera/image_raw | |
ros2 topic find <msg_type> | 按消息类型查找话题 | ros2 topic find geometry_msgs/Twist | |
ros2 topic delay <topic_name> | 测量消息端到端延迟(需含时间戳) | ros2 topic delay /scan | |
| 服务 | ros2 service list | 列出所有活动的服务 | ros2 service list -t(同时显示类型) |
ros2 service type <service_name> | 查看服务的类型 | ros2 service type /spawn | |
ros2 service find <srv_type> | 按服务类型查找服务 | ros2 service find std_srvs/Empty | |
ros2 service call <service_name> <srv_type> <request> | 手动调用服务 | ros2 service call /clear std_srvs/Empty | |
ros2 service info <service_name> | 查看服务的客户端/服务器信息 | ros2 service info /spawn | |
| 参数 | ros2 param list | 列出所有节点的参数 | ros2 param list |
ros2 param get <node_name> <param_name> | 获取指定参数的当前值 | ros2 param get /turtlesim background_g | |
ros2 param set <node_name> <param_name> <value> | 动态设置参数(临时) | ros2 param set /turtlesim background_g 100 | |
ros2 param dump <node_name> | 将节点的参数保存为 YAML 文件 | ros2 param dump /turtlesim | |
ros2 param load <node_name> <param_file> | 从 YAML 文件加载参数 | ros2 param load /turtlesim ./turtlesim.yaml | |
ros2 param delete <node_name> <param_name> | 删除参数 | ros2 param delete /my_node unused_param | |
| 接口 | ros2 interface list | 列出所有可用的接口(msg/srv/action) | ros2 interface list |
ros2 interface show <interface_type> | 查看接口的详细定义 | ros2 interface show geometry_msgs/Twist | |
ros2 interface package <package_name> | 列出指定包内的所有接口 | ros2 interface package sensor_msgs | |
ros2 interface proto <interface_type> | 查看接口的原型(含默认值) | ros2 interface proto turtlesim/Spawn | |
| 动作 | ros2 action list | 列出所有活动的动作 | ros2 action list -t(同时显示类型) |
ros2 action info <action_name> | 查看动作的客户端/服务器信息 | ros2 action info /turtle1/rotate_absolute | |
ros2 action send_goal <action_name> <action_type> <goal> | 手动发送动作目标 | ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}" | |
| 启动 | ros2 launch <pkg> <launch_file> | 使用 launch 文件启动多个节点 | ros2 launch turtlesim multisim.launch.py |
| 运行 | ros2 run <pkg> <executable> | 运行单个节点 | ros2 run turtlesim turtlesim_node |
| 包 | ros2 pkg list | 列出所有已安装的功能包 | ros2 pkg list |
ros2 pkg executable <pkg> | 列出包中的所有可执行文件 | ros2 pkg executable turtlesim |
2.通信机制
2.1.1 支持的数据类型
| IDL 类型 | C++ 类型 | Python 类型 | 说明 |
|---|---|---|---|
bool | bool | bool | 布尔值,true 或 false |
byte | uint8_t | int | 单个字节 |
char | char | str(长度为1) | 单个字符 |
int8,uint8 | int8_t,uint8_t | int | 8位有/无符号整数 |
int16,uint16 | int16_t,uint16_t | int | 16位有/无符号整数 |
int32,uint32 | int32_t,uint32_t | int | 32位有/无符号整数 |
int64,uint64 | int64_t,uint64_t | int | 64位有/无符号整数 |
float32 | float | float | 32位单精度浮点数 |
float64 | double | float | 64位双精度浮点数 |
string | std::string | str | UTF-8 编码的字符串 |
wstring | std::u16string | str | 16位宽字符字符串 |
2.1话题通信
发布/订阅模型,通过定义接口message 作为数据载体,在节点间传输数据,一个节点可以有多个Publisher&&Subscriber,也就是说同一份消息可以发给不同的节点,甚至是多个发送来源(发送者)
2.2 服务通信
请求/响应 的应答机制模型,自定义Service作为消息载体,由客户端节点发送请求,再由服务端节点返回响应。
2.2.1在.srv中引用.msg
本质上srv就是两个消息请求(Request)、请求(Request),所以引用msg相当于把一个定义完整的消息嵌入进来,作为相应或者请求的一部分。
编写srv文件
# 请求部分,引用了自定义消息 my_interfaces/msg/MyMsg my_interfaces/MyMsg request_data int32 request_id --- # 响应部分 bool success string message配置
package.xml你需要在
package.xml中声明两件事:声明这是一个接口包:添加以下内容,告诉构建系统这个包需要生成接口代码。
<buildtool_depend>rosidl_default_generators</buildtool_depend> <exec_depend>rosidl_default_runtime</exec_depend> #主要是下面这个来声明该功能包是个消息接口 <export> <member_of_group>rosidl_interface_packages</member_of_group> </export>声明对消息包的依赖:因为你引用了
my_interfaces包中的消息,所以必须声明对其的构建依赖。xml<build_depend>my_interfaces</build_depend> <exec_depend>my_interfaces</exec_depend>
查找依赖包:在
CMakeLists.txt中,使用find_package查找所有依赖。find_package(rosidl_default_generators REQUIRED) find_package(my_interfaces REQUIRED) # 查找你引用的消息包生成接口代码:调用
rosidl_generate_interfaces函数,在DEPENDENCIES中列出所有被引用的消息包。rosidl_generate_interfaces(${PROJECT_NAME} "srv/MyService.srv" DEPENDENCIES my_interfaces # 这里声明了依赖,是关键! )
2.1.1 自定义message
- 在功能包中新建msg文件夹
- 创建并编辑
.msg文件 编辑配置文件
CMakeLists.txt
find_package(geometry_msgs REQUIRED) find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/<message_name>.msg" DEPENDENCIES geometry_msgs # Add packages that above messages depend on, in this case geometry_msgs for Sphere.msg )package.xml
<!-- 同时声明构建依赖和运行依赖 --> <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>
- 测试
source install/setup.bash ros2 interface show tutorial_interfaces/msg/<message_name>