认识Ros2

概念总览
安装测试
1 | wget http://fishros.com/install -O fishros && . fishros |
1 | ros2 run turtlesim turtlesim_node |
1 | ros2 run turtlesim turtle_teleop_key |
工作空间
工作空间是什么
针对机器人某些功能进行代码开始时,各种编写的代码、参数、脚本等文件,也需要放置在某一个文件夹里进行管理,这个文件夹在ROS系统中就叫做工作空间。
src,代码空间,未来编写的代码、脚本,都需要人为的放置到这里;
build,编译空间,保存编译过程中产生的中间文件;
install,安装空间,放置编译得到的可执行文件和脚本;
log,日志空间,编译和运行过程中,保存各种警告、错误、信息等日志。
创建工作空间
1 | $ mkdir -p ~/ros2_test1/src |
自动安装依赖
1 | $ sudo apt install -y python3-pip |
编译工作空间
依赖安装完成后,就可以使用如下命令编译工作空间啦,如果有缺少的依赖,或者代码有错误,编译过程中会有报错,否则编译过程应该不会出现任何错误:
1 | $ sudo apt install python3-colcon-ros |
设置环境变量
编译成功后,为了让系统能够找到我们的功能包和可执行文件,还需要设置环境变量:
1 | $ echo "source ~/<工作空间>/install/setup.sh" >> ~/.bashrc # 所有终端均生效 |
1 | $ source install/local_setup.sh # 仅在当前终端生效 |
功能包
我们把不同功能的代码划分到不同的功能包中,尽量降低他们之间的耦合关系,当需要在ROS社区中分享给别人的时候,只需要说明这个功能包该如何使用,别人很快就可以用起来了。
所以功能包的机制,是提高ROS中软件复用率的重要方法之一。
创建功能包
1 | $ cd ~/ros2_test1/src |
1 | ros2 pkg create --build-type <build-type> <package_name> |
- C++功能包创建
1 | ros2 pkg create study_helloworld_cpp --build-type ament_cmake --dependencies rclcpp --node-name helloworld |
- Python功能包创建
1 | ros2 pkg create study_helloworld_py --build-type ament_python --dependencies rclpy --node-name helloworld |
pkg:表示功能包相关的功能;
create:表示创建功能包;
build-type:表示新创建的功能包是C++还是Python的,如果使用C++或者C,那这里就跟ament_cmake,如果使用Python,就跟ament_python;
package_name:新建功能包的名字。
编辑C++测试代码
1 |
|
VSCode头文件报错解决方法:设置头文件环境路径”/opt/ros/humble/include/**”
1 | import rclpy |
编译功能包
在创建好的功能包中,我们可以继续完成代码的编写,之后需要编译和配置环境变量,才能正常运行
1 | $ cd ~/ros2_test1 |
节点
节点在机器人系统中的职责就是执行某些具体的任务,从计算机操作系统的角度来看,也叫做进程;
每个节点都是一个可以独立运行的可执行文件,比如执行某一个python程序,或者执行C++编译生成的结果,都算是运行了一个节点;
既然每个节点都是独立的执行文件,那自然就可以想到,得到这个执行文件的编程语言可以是不同的,比如C++、Python,乃至Java、Ruby等更多语言。
这些节点是功能各不相同的细胞,根据系统设计的不同,可能位于计算机A,也可能位于计算机B,还有可能运行在云端,这叫做分布式,也就是可以分布在不同的硬件载体上;
每一个节点都需要有唯一的命名,当我们想要去找到某一个节点的时候,或者想要查询某一个节点的状态时,可以通过节点的名称来做查询。
创建节点流程
- 编程接口初始化
- 创建节点并初始化
- 实现节点功能
- 销毁节点并关闭接口
1 | $ ros2 run learning_node node_helloworld |
1 | #!/usr/bin/env python3 |
在一个ROS机器人的系统中,节点并不是孤立的,他们之间会有很多种机制保持联系
话题
节点实现了机器人各种各样的功能,但这些功能并不是独立的,之间会有千丝万缕的联系,其中最重要的一种联系方式就是话题,它是节点间传递数据的桥梁。
话题数据传输的特性是从一个节点到另外一个节点,发送数据的对象称之为发布者,接收数据的对象称之为订阅者,每一个话题都需要有一个名字,传输的数据也需要有固定的数据类型。
服务
话题通信可以实现多个ROS节点之间数据的单向传输,使用这种异步通信机制,发布者无法准确知道订阅者是否收到消息,ROS另外一种常用的通信方法——服务,可以实现类似你问我答的同步通信效果。
1 | $ ros2 run learning_service service_adder_server |
客户端代码解析
1 | #!/usr/bin/env python3 |
服务端代码解析
1 | #!/usr/bin/env python3 |
通信接口
软件开发中,接口的使用就更多了,比如我们在编写程序时,使用的函数和函数的输入输出也称之为接口,每一次调用函数的时候,就像是把主程序和调用函数通过这个接口连接到一起,系统才能正常工作。
更为形象的是图形化编程中使用的程序模块,每一个模块都有固定的结构和形状,只有两个模块相互匹配,才能在一起工作,这就很好的讲代码形象化了。
所以什么是接口,它是一种相互关系,只有彼此匹配,才能建立连接。
动作
一对多通信
和服务一样,动作通信中的客户端可以有多个,大家都可以发送运动命令,但是服务器端只能有一个,毕竟只有一个机器人,先执行完成一个动作,才能执行下一个动作。
同步通信
既然有反馈,那动作也是一种同步通信机制,之前我们也介绍过,动作过程中的数据通信接口,使用.action文件进行定义。
由服务和话题合成
大家再仔细看下上边的动图,是不是还会发现一个隐藏的秘密。
动作的三个通信模块,竟然有两个是服务,一个是话题,当客户端发送运动目标时,使用的是服务的请求调用,服务器端也会反馈一个应带,表示收到命令。动作的反馈过程,其实就是一个话题的周期发布,服务器端是发布者,客户端是订阅者。
没错,动作是一种应用层的通信机制,其底层就是基于话题和服务来实现的。
1 | bool enable # 定义动作的目标,表示动作开始的指令 |
通信模型
参数
全局字典
在ROS系统中,参数是以全局字典的形态存在的,什么叫字典?就像真实的字典一样,由名称和数值组成,也叫做键和值,合成键值。或者我们也可以理解为,就像编程中的参数一样,有一个参数名 ,然后跟一个等号,后边就是参数值了,在使用的时候,访问这个参数名即可。
可动态监控
在ROS2中,参数的特性非常丰富,比如某一个节点共享了一个参数,其他节点都可以访问,如果某一个节点对参数进行了修改,其他节点也有办法立刻知道,从而获取最新的数值。这在参数的高级编程中,大家都可能会用到。
分布式通信
可以实现多计算平台上的任务分配
DDS
DDS的核心是通信,能够实现通信的模型和软件框架非常多,这里我们列出常用的四种模型。
点对点模型
许多客户端连接到一个服务端,每次通信时,通信双方必须建立一条连接。当通信节点增多时,连接数也会增多。而且每个客户端都需要知道服务器的具体地址和所提供的服务,一旦服务器地址发生变化,所有客户端都会受到影响。
Broker模型
针对点对点模型进行了优化,由Broker集中处理所有人的请求,并进一步找到真正能响应该服务的角色。这样客户端就不用关心服务器的具体地址了。不过问题也很明显,Broker作为核心,它的处理速度会影响所有节点的效率,当系统规模增长到一定程度,Broker就会成为整个系统的性能瓶颈。更麻烦是,如果Broker发生异常,可能导致整个系统都无法正常运转。之前的ROS1系统,使用的就是类似这样的架构。
广播模型
所有节点都可以在通道上广播消息,并且节点都可以收到消息。这个模型解决了服务器地址的问题,而且通信双方也不用单独建立连接,但是广播通道上的消息太多了,所有节点都必须关心每条消息,其实很多是和自己没有关系的。
DDS模型
这种模型与广播模型有些类似,所有节点都可以在DataBus上发布和订阅消息。但它的先进之处在于,通信中包含了很多并行的通路,每个节点可以只关心自己感兴趣的消息,忽略不感兴趣的消息,有点像是一个旋转火锅,各种好吃的都在这个DataBus传送,我们只需要拿自己想吃的就行,其他的和我们没有关系。
DDS在ROS2中的应用:
常用工具
Launch、TF、URDF、Gazebo、Rviz、Rqt