赞
踩
refer:古月 & 小鱼
相比ros1,ros2基于DDS实现去中心化,无需master节点,节点之间采用自发现机制进行通信。
相比API接口更具通用性,使用了新的编译器
支持更多的os
DDS(Data Distribution Service,数据分发服务)是一种用于实时系统的开放式通信协议和架构。
DDS提供了一种分布式数据架构,其中数据生产者和消费者之间通过数据交换实现通信。它的核心概念是数据发布者(Publishers)和数据订阅者(Subscribers),它们通过主题(Topics)进行连接。发布者发布数据到特定的主题,而订阅者订阅感兴趣的主题,并接收相应的数据。topic类似杂志,pub就是编辑,sub就是订阅的读者。
由于不同厂家的DDS软件接口协议不同,ROS2制定了一个标准接口:ROS Middleware,简称RMW。让厂家去适配。
节点和主题之间的关系可以描述为:
发布者节点将消息发布到一个或多个主题上。
订阅者节点通过订阅感兴趣的主题来接收消息。
通过节点和主题的结合使用,ROS 2系统可以实现复杂的通信和数据交换,从而构建各种类型的机器人应用程序或其他实时系统。
鱼香ROS一键安装指令:wget http://fishros.com/install -O fishros && . fishros
cd
语法:cd <目录路径>
功能:改变工作目录。若没有指定“目录路径”,则回到用户的主目录
pwd
语法:pwd
功能:此命令显示出当前工作目录的绝对路径
mkdir
语法:mkdir [选项] <目录名称>
功能:创建一个目录/文件夹
ls
语法:ls [选项] [目录名称…]
功能:列出目录/文件夹中的文件列表
gedit
语法:gedit <文件名称>
功能:打开gedit编辑器编辑文件,若没有此文件则会新建
mv
语法:mv [选项] <源文件或目录> <目地文件或目录>
功能:为文件或目录改名或将文件由一个目录移入另一个目录中
cp
语法:cp [选项] <源文件名称或目录名称> <目的文件名称或目录名称>
功能:把一个文件或目录拷贝到另一文件或目录中,或者把多个源文件复制到目标目录中
rm
语法:rm [选项] <文件名称或目录名称…>
功能:该命令的功能为删除一个目录中的一个或多个文件或目录,它也可以将某个目录及其下的所有文件及子目录均删除。对于链接文件,只是删除了链接,原有文件均保持不变
sudo
语法:sudo [选项] [指令]
功能:以系统管理员权限来执行指令
easoom@easoom-virtual-machine:~$ ros2 --help usage: ros2 [-h] Call `ros2 <command> -h` for more detailed usage. ... ros2 is an extensible command-line tool for ROS 2. optional arguments: -h, --help show this help message and exit Commands: action Various action related sub-commands bag Various rosbag related sub-commands component Various component related sub-commands daemon Various daemon related sub-commands doctor Check ROS setup and other potential issues interface Show information about ROS interfaces launch Run a launch file lifecycle Various lifecycle related sub-commands multicast Various multicast related sub-commands node Various node related sub-commands param Various param related sub-commands pkg Various package related sub-commands run Run a package specific executable security Various security related sub-commands service Various service related sub-commands topic Various topic related sub-commands wtf Use `wtf` as alias to `doctor` Call `ros2 <command> -h` for more detailed usage.
即工程文件,包含编写的代码、参数、脚本等文件。
典型工作空间:
src,代码空间,未来编写的代码、脚本,都需要人为的放置到这里;
build,编译空间,保存编译过程中产生的中间文件;
install,安装空间,放置编译得到的可执行文件和脚本;
log,日志空间,编译和运行过程中,保存各种警告、错误、信息等日志。
总体来讲,这四个空间的文件夹,我们绝大部分操作都是在src中进行的,编译成功后,就会执行install里边的结果,build和log两个文件夹用的很少。
将不同功能的代码整合打包即为功能包。
$ ros2 pkg create --build-type <build-type> <package_name>
ros2命令中:
pkg:表示功能包相关的功能;
create:表示创建功能包;
build-type:表示新创建的功能包是C++还是Python的,如果使用C++或者C,那这里就跟ament_cmake,如果使用Python,就跟ament_python;
package_name:新建功能包的名字。
创建CPP和python的功能包:
$ cd ~/dev_ws/src $ ros2 pkg create --build-type ament_cmake learning_pkg_c # C++ $ ros2 pkg create --build-type ament_python learning_pkg_python # Python
CPP的功能包中必然存在两个文件:package.xml和CMakerLists.txt。
package.xml文件的主要包含功能包的版权描述,和各种依赖的声明。
CMakeLists.txt文件是编译规则,C++代码需要编译才能运行,所以必须要在该文件中设置如何编译,使用CMake语法。
pyhton的功能包中也会有这两个文件:package.xml和setup.py。
package.xml文件的主要内容和C++版本功能包一样,包含功能包的版权描述,和各种依赖的声明。
setup.py文件里边也包含一些版权信息,除此之外,还有“entry_points”配置的程序入口。
节点是一个单独的进程,每个节点都是独立运行的可执行文件,可以分布在不同的硬件平台上,编程语言也可以不同,节点之间需要唯一命名。
编程接口初始化
创建节点并初始化
实现节点功能
销毁节点并关闭接口
节点之间的一种通信方式
发布-(话题)-订阅
异步通信
可以多对多
消息接口.msg
编程接口初始化
创建节点并初始化
创建发布者对象
创建并填充话题消息
发布话题消息
销毁节点并关闭接口
编程接口初始化
创建节点并初始化
创建订阅者对象
回调函数处理话题数据
销毁节点并关闭接口
topic本身是没有存储功能的,发布者一旦发布,订阅者需要第一时间接受下来,但可以不第一时间处理。对于已经发布的消息,可以设置一定的历史消息深度,让订阅者能查询历史消息。
你问我答,同步通信。
类似服务器--客户端,即一对多通信,服务器只能有一个,客户端可以有多个。
分为请求数据和反馈数据,格式为.srv。
编程接口初始化
创建节点并初始化
创建服务器端对象
通过回调函数处进行服务
向客户端反馈应答结果
销毁节点并关闭接口
编程接口初始化
创建节点并初始化
创建客户端对象
创建并发送请求数据
等待服务器端应答数据
销毁节点并关闭接口
$ ros2 service list # 查看服务列表 $ ros2 service type <service_name> # 查看服务数据类型 $ ros2 service call <service_name> <service_type> <service_data> # 发送服务请求
ROS有三种常用的通信机制,分别是话题、服务、动作,通过每一种通信种定义的接口,各种节点才能有机的联系到一起。
语言无关
比如这里看到的int32表示32位的整型数,int64表示64位的整型数,bool表示布尔值,还可以定义数组、结构体,这些定义在编译过程中,会自动生成对应到C++、Python等语言里的数据结构。
话题通信接口的定义使用的是.msg文件,由于是单向传输,只需要描述传输的每一帧数据是什么就行,比如在这个定义里,会传输两个32位的整型数,x、y,我们可以用来传输二维坐标的数值。
服务通信接口的定义使用的是.srv文件,包含请求和应答两部分定义,通过中间的“---”区分,比如之前我们学习的加法求和功能,请求数据是两个64位整型数a和b,应答是求和的结果sum。
动作是另外一种通信机制,用来描述机器人的一个运动过程,使用.action文件定义,比如我们让小海龟转90度,一边转一边周期反馈当前的状态,此时接口的定义分成了三个部分,分别是动作的目标,比如是开始运动,运动的结果,最终旋转的90度是否完成,还有一个周期反馈,比如每隔1s反馈一下当前转到第10度、20度还是30度了,让我们知道运动的进度。
ros2中原生提供了标准接口:我们可以在ROS安装路径中的share文件夹中找到,涵盖众多标准定义
package.xml文件的主要内容如下,包含功能包的版权描述,和各种依赖的声明。
CMakeLists.txt文件是编译规则,C++代码需要编译才能运行,所以必须要在该文件中设置如何编译,使用CMake语法。
定义,路径:learning_interface/srv/GetObjectPosition.srv
定义中有两个部分,上边是获取目标位置的指令,get为true的话,就表示我们需要一次位置,服务端就会反馈这个x、y坐标了。
bool get # 获取目标位置的指令 --- int32 x # 目标的X坐标 int32 y # 目标的Y坐标
CMakeLists.txt中配置编译选项
完成定义后,还需要在功能包的CMakeLists.txt中配置编译选项,让编译器在编译过程中,根据接口定义,自动生成不同语言的代码。
... find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "srv/GetObjectPosition.srv" ) ..
package.xml中添加功能依赖
功能包的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> ...
服务通信接口程序调用
# 客户端 ··· from learning_interface.srv import GetObjectPosition # 自定义的服务接口 class objectClient(Node): def __init__(self, name): super().__init__(name) # ROS2节点父类初始化 self.client = self.create_client(GetObjectPosition, 'get_target_position') while not self.client.wait_for_service(timeout_sec=1.0): self.get_logger().info('service not available, waiting again...') self.request = GetObjectPosition.Request() def send_request(self): self.request.get = True self.future = self.client.call_async(self.request) ··· #服务端 ··· self.srv = self.create_service(GetObjectPosition, # 创建服务器对象(接口类型、服务名、服务器回调函数) 'get_target_position', self.object_position_callback) ···
定义
话题消息的内容是一个位置,我们使用x、y坐标值进行描述。
文件路径:learning_interface/msg/ObjectPosition.msg
int32 x # 表示目标的X坐标 int32 y # 表示目标的Y坐标
CMakeLists.txt中配置编译选项
... find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "msg/ObjectPosition.msg" ) ...
程序调用
发布者 ··· from learning_interface.msg import ObjectPosition # 自定义的目标位置消息 def __init__(self, name): super().__init__(name) # ROS2节点父类初始化 self.sub = self.create_subscription( Image, 'image_raw', self.listener_callback, 10) # 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度) self.pub = self.create_publisher( ObjectPosition, "object_position", 10) # 创建发布者对象(消息类型、话题名、队列长度) self.cv_bridge = CvBridge() # 创建一个图像转换对象,用于OpenCV图像与ROS的图像消息的互相转换 self.objectX = 0 self.objectY = 0 ··· ----- 订阅者 ··· from learning_interface.msg import ObjectPosition # 自定义的目标位置消息 def __init__(self, name): super().__init__(name) # ROS2节点父类初始化 self.sub = self.create_subscription(\ ObjectPosition, "/object_position", self.listener_callback, 10) # 创建订阅者对象(消息类型、话题名、订阅者回调函数、队列长度 ···
$ ros2 interface list # 查看系统接口列表 $ ros2 interface show <interface_name> # 查看某个接口的详细定义 $ ros2 interface package <package_name> # 查看某个功能包中的接口定义
也是一种通信机制,顾名思义,对机器人的一段完整行为进行描述和管理。
定义格式
bool enable # 定义动作的目标,表示动作开始的指令 --- bool finish # 定义动作的结果,表示是否成功执行 --- int32 state # 定义动作的反馈,表示当前执行到的位置
CMakeLists.txt中配置编译选项
... find_package(rosidl_default_generators REQUIRED) rosidl_generate_interfaces(${PROJECT_NAME} "action/MoveCircle.action" ) ...
服务器(机器人),客户端(控制器)
一对多通信,机器人只能有一个,控制器可以有多个。
同步通信
“动作”是应用层通信机制,由话题和服务搭建而成
大致逻辑
# 客户端(python) ''' 注意三个回调函数 1、 目标发送后等待服务器反馈的回调函数 2、 接收服务器发送的反馈数据的回调函数 3、 异步询问是否完成动作的回调函数 一、定义action接口 二、初始化action对象 三、send_goal();发送目标函数 1. 发送目标函数 2. 设置 反馈接收回调函数 a. 反馈数据处理 3. 设置 接收目标函数回调函数 a. if 拒绝目标 return b. if 接受目标,异步获取执行结果反馈,并设置对应回调函数 (1) 动作完成回调函数 '''
也是一种数据传输方式,类似全局变量。
参数是ROS机器人系统中的全局字典,可以运行多个节点中共享数据。
在ROS2中,参数的特性非常丰富,比如某一个节点共享了一个参数,其他节点都可以访问,如果某一个节点对参数进行了修改,其他节点也有办法立刻知道,从而获取最新的数值。这在参数的高级编程中,大家都可能会用到。
$ ros2 param list # 查询系统中的参数 $ ros2 param describe turtlesim background_b # 查看某个参数的描述信息 $ ros2 param get turtlesim background_b # 查询某个参数的值 $ ros2 param set turtlesim background_b 10 # 修改某个参数的值 $ ros2 param dump turtlesim >> turtlesim.yaml # 将某个节点的参数保存到参数文件中 $ ros2 param load turtlesim turtlesim.yaml # 一次性加载某一个文件中的所有参数
略
将任务拆分,分配给多个计算平台。基于分布式通信实现多计算平台的任务分配。
基于同一局域网下,对多个ros设备建立连接,当作一个整体使用。
可以设置不同的域,对设备进行分组,只有相同ID才能通信。
$ export ROS_DOMAIN_ID=<your_domain_id>
DDS的全称是Data Distribution Service,也就是数据分发服务,以数据为中心。
类似广播的模式,将数据放在一个总的,含有众多并行通路的bus上,但挂载在bus上的设备只接收自己关心的数据。
QoS是一种网络传输策略,应用程序指定所需要的网络传输质量行为,QoS服务实现这种行为要求,尽可能地满足客户对通信质量的需求,可以理解为数据提供者和接收者之间的合约。
DEADLINE策略,表示通信数据必须要在每次截止时间内完成一次通信;
HISTORY策略,表示针对历史数据的一个缓存大小;
RELIABILITY策略,表示数据通信的模式,配置成BEST_EFFORT,就是尽力传输模式,网络情况不好的时候,也要保证数据流畅,此时可能会导致数据丢失,配置成RELIABLE,就是可信赖模式,可以在通信中尽量保证图像的完整性,我们可以根据应用功能场景选择合适的通信模式;
DURABILITY策略,可以配置针对晚加入的节点,也保证有一定的历史数据发送过去,可以让新节点快速适应系统。
··· from rclpy.qos import QoSProfile, QoSReliabilityPolicy, QoSHistoryPolicy # ROS2 QoS类 def __init__(self, name): super().__init__(name) # ROS2节点父类初始化 qos_profile = QoSProfile( # 创建一个QoS原则 # reliability=QoSReliabilityPolicy.BEST_EFFORT, reliability=QoSReliabilityPolicy.RELIABLE, history=QoSHistoryPolicy.KEEP_LAST, depth=1 ) self.pub = self.create_publisher(String, "chatter", qos_profile) # 创建发布者对象(消息类型、话题名、QoS原则) self.timer = self.create_timer(0.5, self.timer_callback) # 创建一个定时器(单位为秒的周期,定时执行的回调函数) ···
ROS系统中多节点启动与配置的一种脚本。
ROS2中的Launch文件就是基于Python描述的。
exp:
from launch import LaunchDescription # launch文件的描述类 from launch_ros.actions import Node # 节点启动的描述类 def generate_launch_description(): # 自动生成launch文件的函数 return LaunchDescription([ # 返回launch文件的描述信息 Node( # 配置一个节点的启动 package='learning_topic', # 节点所在的功能包 executable='topic_helloworld_pub', # 节点的可执行文件 ), Node( # 配置一个节点的启动 package='learning_topic', # 节点所在的功能包 executable='topic_helloworld_sub', # 节点的可执行文件名 ), ])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。