前言
ROS 工具箱提供了一个连接 MATLAB® 和 Simulink® 与机器人操作系统(ROS 和 ROS 2)的接口。利用该工具箱,您可以设计 ROS 节点网络,并将 MATLAB 或 Simulink 生成的 ROS 节点与现有的 ROS 网络相结合。
工具箱包括 MATLAB 函数和 Simulink 块,可通过记录、导入和回放 rosbag 文件来可视化和分析 ROS 数据。您还可以连接到实时 ROS 网络,访问 ROS 消息。
该工具箱可让你通过桌面仿真和连接外部机器人仿真器(如 Gazebo)或硬件来验证 ROS 节点。ROS 工具箱支持 C++ 和 CUDA® 代码生成(使用 MATLAB Coder™、Simulink Coder 和 GPU Coder™),使您能够从 MATLAB 脚本或 Simulink 模型自动生成 ROS 节点,并部署到模拟或物理硬件上。支持 Simulink 外部模式后,当模型在硬件上运行时,你可以查看信息并更改参数。
一、ROS 2 入门
本示例展示了如何在 MATLAB 中设置 ROS 2,并获取有关 ROS 2 网络和 ROS 2 消息的信息。
机器人操作系统 2(ROS 2)是 ROS 的第二个版本,它是一个通信接口,可以让机器人系统的不同部分发现、发送和接收数据。支持 ROS 2 的 MATLAB® 是一个函数库,可让您与支持 ROS 2 的物理机器人或机器人模拟器(如 Gazebo®)交换数据。ROS 2 建立在数据分发服务(DDS)的基础上,这是一个端到端的中间件,具有发现、序列化和传输等功能。这些功能符合 ROS 2 的设计原则,如分布式发现和控制不同的传输 "服务质量 "选项。DDS 使用实时发布-订阅(RTPS)协议,可通过 UDP 等不可靠的网络协议进行通信。如需了解更多信息,请参阅 RTPS。
要了解 ROS,请参阅 ROS 入门。
1.1 ROS 2 术语
- ROS 2 网络由通过 ROS 2 网络进行通信的机器人系统不同部分(如规划器或摄像头接口)组成。网络可以分布在多台机器上。
- ROS 2节点是一个包含相关ROS 2能力(如发布者和订阅者)集合的实体。一个 ROS 2 网络可以有多个 ROS 2 节点。
- 发布者和订阅者是处理数据的不同类型的 ROS 2 实体。它们使用消息交换数据。
- 发布者向特定话题(如 “里程计”)发送消息,该话题的订阅者接收这些消息。一个话题可以关联多个发布者和订阅者。
- 域是网络的物理分段。它由一个称为域 ID 的唯一整数值标识。默认情况下,域 ID 为 0。
- ROS 2 网络中的每个节点在创建时都会向同一域 ID 中的其他节点公布自己的存在。
- ROS 2 网络建立在数据分发服务(DDS)基础上,因此可以在分布式网络中连接多个节点。更多信息,请参阅在 ROS 中间件实现之间切换。
- RTPS(实时发布者-订阅者)协议为 ROS 2 网络提供了在不可靠网络条件下发送信息的功能。
- ROS 2 提供各种服务质量(QoS)策略,让你可以调整节点之间的通信。如需了解更多信息,请参阅管理 ROS 2 中的服务质量策略。
更多信息,请参阅机器人操作系统2(ROS 2)和 ROS 2 网站上的概念部分。
1.2 启动 ROS 2 网络
与 ROS 不同,ROS 2 无需在 MATLAB 中进行初始化。ROS 2 网络会自动从创建节点开始。
使用 ros2node
创建节点。
test1 = ros2node("/test1")
test1 = ros2node - 属性: Name: '/test1' ID: 0
使用 ros2 node list
查看 ROS 2 网络中的所有节点。
ros2 node list
/test1
使用 clear
关闭 ROS 2 网络中的节点。
clear test1
使用 exampleHelperROS2CreateSampleNetwork
为 ROS 网络添加三个节点,其中包括样本发布者和订阅者。
exampleHelperROS2CreateSampleNetwork
使用 ros2 node list
查看 ROS 2 网络中的所有节点。
ros2 node list
/tp367a7a03_c5b6_46f8_962 /tp3cbf47a7_c1c8_474c_bb /tp6bb8a4e5_2f37_
这是创建样本节点后 ROS 2 网络的可视化表示。在本示例的其余部分中,请将其作为探索 ROS 2 网络的参考。
1.3 话题和服务质量策略
运行命令 ros2 topic list
查看 ROS 2 网络中的可用话题。该命令会返回三个活动话题: /pose、/parameter_events
和 /scan
。话题 /parameter_events
是 ROS 2 网络中始终存在的全局话题。节点使用 /paramater_events
话题监控或更改网络中的参数。您创建的 /scan
和 /pose
话题是示例网络的一部分。
ros2 topic list
/parameter_events /pose /rosout /scan
每个主题都与一种信息类型相关联。运行命令 ros2 topic list -t
可以查看每个主题的信息类型。
ros2 topic list -t
Topic MessageType _____________________ _________________________________ {'/parameter_events'} {'rcl_interfaces/ParameterEvent'} {'/pose' } {'geometry_msgs/Twist' } {'/rosout' } {'rcl_interfaces/Log' } {'/scan' } {'sensor_msgs/LaserScan' }
服务质量(QoS)策略选项可改变发布者和订阅者处理和交换信息的方式。
- 使用
History
和Depth
QoS 策略,可根据在处理队列中放置报文的方式确定通信对象的行为。将History
指定为以下选项之一。
- “keeplast” - 删除信息,只保留最新信息。
- “keepall”(全部保留)- 保留队列中收到的所有报文,直到处理完毕。
- 使用
Reliability
QoS 策略保证向用户发送信息。将可靠性指定为以下选项之一。
- “reliable”- 确保发布者持续向订户发送信息,直到订户确认收到信息。
- “besteffort”- 允许发布者只发送一次信息。
- 使用
Durability
QoS 策略和Depth
输入来控制晚加入连接的信息持久性。将Durability
指定为以下选项之一。
- “transientlocal”(临时)- 如果订阅者在发布者首次发送信息后加入网络,则发布者会向订阅者发送持久化信息。
- “volatile”(易失性)- 发布者在发送信息后不会持久化信息。订阅者不会向发布者请求持久化信息。
1.4 消息
发布者和订阅者使用 ROS 2 消息交换信息。每条 ROS 2 消息都有一个相关的消息类型,它定义了消息中的数据类型和信息布局。更多信息,请参阅 “使用基本 ROS 2 消息”。
使用 ros2 msg show
查看消息类型的属性。geometry_msgs/Twist
消息类型有两个属性:Linear
和角度 Angular
。每个属性都是 geometry_msgs/Vector3
类型的信息,而 geometry_msgs/Vector3
又有三个 double 类型的属性。
ros2 msg show geometry_msgs/Twist
# This expresses velocity in free space broken into its linear and angular parts. Vector3 linear Vector3 angular
ros2 msg show geometry_msgs/Vector3
# This represents a vector in free space. # This is semantically different than a point. # A vector is always anchored at the origin. # When a transform is applied to a vector, only the rotational component is applied. float64 x float64 y float64 z
使用 ros2 msg list
查看 MATLAB 中可用消息类型的完整列表。
1.5 从 ROS 2 网络断开连接
使用 exampleHelperROS2ShutDownSampleNetwork
可从 ROS 2 网络中移除样本节点、发布者和订阅者。要移除自己的节点,请在节点、发布者或订阅者对象中使用 clear
。
exampleHelperROS2ShutDownSampleNetwork
1.6 DDS 和 RMW 实施
在 MATLAB® 和 Simulink® 中使用 ROS 2 时,您可以切换 RMW 实现来使用数据分发服务(DDS)。要配置所需的 RMW 实现,请按照以下步骤操作。
- 在 MATLAB 工具条 "环境 "部分的 "主页 "选项卡下,打开 “首选项”。
- 在 ROS 工具箱首选项对话框中配置 Python™ 环境,并从 ROS 中间件 (RMW) 实现下拉列表中选择一个实现。默认实现为
rmw_fastrtps_cpp
。
- 单击 “配置并切换到自定义 RMW 实现”,启动 ROS 中间件配置对话框,切换到自定义 RMW 实现。
- 安装并构建自定义 RMW 实现软件包,以验证使用所选自定义 RMW 实现创建 ROS 2 节点。
二、连接到 ROS 2 网络
ROS 2 网络由多个 ROS 2 节点组成。与 ROS 不同,ROS 2 基于数据分发标准(DDS),这是一个端到端的中间件,可提供发现、序列化和传输等功能。这些功能符合 ROS 2 的设计原则,如分布式发现和控制不同的传输 "服务质量 "选项。
要连接到 ROS 1 网络,请参阅连接到 ROS 网络。
使用 ROS 2 时,通常需要遵循以下步骤:
- 连接到 ROS 2 网络 - 要连接到 ROS 2 网络,必须在 MATLAB 中创建一个 ROS 2 节点,并指定网络域 ID。
- 交换数据–连接后,MATLAB 将通过发布者和订阅者与同一域 ID 中的其他 ROS 2 节点交换数据。
- 从 ROS 2 网络断开连接 - 从 ROS 2 网络断开 MATLAB ROS 2 节点、发布者和订阅者的连接。
2.1 在默认域中创建 ROS 2 节点
使用 ros2node
在默认域中创建一个节点,其 ID 为 0。 节点与同一域中的其他节点通信,但不知道其他域中的节点。
defaultNode = ros2node("/default_node")
defaultNode = ros2node - 属性: Name: '/default_node' ID: 0
使用 clear
删除对节点的引用,从而将其从 ROS 2 网络中删除。
clear defaultNode
2.2 在不同域上创建 ROS 2 节点
要在非默认域中创建节点,请明确指定域 ID 作为 ros2node
的第二个输入参数。下面的 newDomainNode
将在 ID 25 指定的域中创建。
newDomainNode = ros2node("/new_domain_node",25)
newDomainNode = ros2node - 属性: Name: '/new_domain_node' ID: 25
要查看特定域的网络信息,请将 ID 作为参数提供给 ros2
函数。以下命令将显示域 ID 为 25 的所有节点。
ros2("node","list","DomainID",25)
/new_domain_node
2.3 更改默认域 ID
如果没有向 node 或 ros2 命令明确提供域 ID,它们默认使用 ROS_DOMAIN_ID
环境变量的值。使用 getenv
查看当前值。如果该环境变量未设置或未设置为有效值,则将使用默认的 0 域名 ID。
getenv("ROS_DOMAIN_ID")
ans = 空的 0×0 char 数组
可以使用 setenv
命令设置 ROS_DOMAIN_ID
。
setenv("ROS_DOMAIN_ID","25") envDomainNode = ros2node("/env_domain_node")
envDomainNode = ros2node - 属性: Name: '/env_domain_node' ID: 25
ros2 函数提供该环境变量指定的网络信息。使用 ros2 node list
查看域 ID 为 25 的节点。
ros2 node list
/env_domain_node /new_domain_node
将 ROS_DOMAIN_ID 重置为默认值。
setenv("ROS_DOMAIN_ID","")
2.4 ROS 2 网络通信
要连接到现有的 ROS 2 网络,请在所需的域中创建一个节点。ROS 2 网络会通过一种名为 "发现 "的机制,自动检测在同一域中创建的任何新节点。
启动时,ROS 2 中的每个节点都会向同一域中的其他节点发出自己存在的广告。其他节点会响应这一广告,向新节点提供自己的信息。拥有通信对象(如发布者和订阅者)的节点,如果拥有服务质量(QoS)设置兼容的相应对象,就能与其他节点建立连接。有关 QoS 设置的更多信息,请参阅《ROS 2 中的服务质量策略管理》。
发现是一个持续的过程,它能让新节点在创建时加入网络。每个节点都在监控 ROS 2 网络,其作用类似于 ROS 网络中的 ROS 主节点。当节点离线时,也会向其他节点公布自己的缺席。
新的 ROS 2 节点向现有节点发送广告。现有节点响应广告,然后建立持续通信。
2.5 子网外的 ROS 通信
子网是将 IP 网络划分为多个较小网段的逻辑分区。ROS 2 节点可与同一子网内的其他节点通信。要检测子网外的节点,可创建一个 DEFAULT_FASTRTPS_PROFILE.xml
文件,配置 MATLAB 使用的特定 DDS 实现。在地址元素内添加要与之通信的子网外系统的 IP 地址列表。请注意,要进行通信,两个系统都必须在各自的 DEFAULT_FASTRTPS_PROFILE.xml
文件中指定对方的地址。将 domainId
元素设置为用于通信的网络的适当值。
将此文件保存在 MATLAB 当前工作目录中。在 MATLAB 之外使用 ROS 2 的系统应将此文件放在运行 ROS 2 应用程序的同一目录下。下面是 DEFAULT_FASTRTPS_PROFILES.xml
文件的示例。
<?xml version="1.0" encoding="UTF-8" ?> <profiles> <participant profile_name="participant_win" is_default_profile="true"> <rtps> <builtin> <metatrafficUnicastLocatorList> <locator/> </metatrafficUnicastLocatorList> <initialPeersList> <locator> <udpv4> <address>192.34.17.36</address> </udpv4> </locator> <locator> <udpv4> <address>182.30.45.12</address> </udpv4> </locator> <locator> <udpv4> <address>194.158.78.29</address> </udpv4> </locator> </initialPeersList> </builtin> </rtps> </participant> </profiles>
ROS 2 会向 DEFAULT_FASTRTPS_PROFILES.xml
中列出 IP 地址的系统中的节点发布信息。如果 DEFAULT_FASTRTPS_PROFILES.xml
不存在或不包含正确的 IP 地址,则不会收到来自子网外其他机器中节点的信息。
三、与 ROS 2 发布者和订阅者交换数据
本例展示了如何在 ROS 2 网络中发布和订阅主题。
ROS 2 节点交换数据的主要机制是发送和接收消息。消息在话题上传输,每个话题在 ROS 2 网络中都有一个唯一的名称。如果节点想共享信息,就必须使用发布者向话题发送数据。要接收信息的节点必须使用同一话题的订阅者。除了唯一的名称外,每个话题还有一个信息类型,它决定了允许在特定话题中传输的信息类型。
这种发布者与订阅者之间的通信具有以下特点:
- 主题用于多对多通信。多个发布者可以向同一个主题发送信息,多个订阅者可以接收信息。
- 发布者和订阅者通过话题解耦,可以任意顺序创建和销毁。即使没有活跃的订阅者,也可以向话题发布信息。
除了如何在 ROS 2 网络中发布和订阅主题外,本示例还展示了如何
- 等待收到新消息,或
- 使用回调在后台处理新消息
先决条件 开始使用 ROS 2,连接到 ROS 2 网络。
3.1 订阅并等待信息
创建一个包含多个发布者和订阅者的 ROS 2 示例网络。
exampleHelperROS2CreateSampleNetwork
使用 ros2 topic list
查看哪些话题可用。
ros2 topic list
/parameter_events /pose /rosout /scan
假设你想订阅 /scan
主题。使用 ros2subscriber
订阅 /scan
主题。指定订阅节点的名称。如果 ROS 2 网络中已经存在该主题,ros2subscriber
会自动检测其消息类型,因此无需指定。
detectNode = ros2node("/detection"); pause(5) laserSub = ros2subscriber(detectNode,"/scan"); pause(5)
使用 receive
等待新信息。指定超时时间为 10 秒。输出 scanData
包含接收到的报文数据,status
表示是否成功接收到报文,stustext
则提供有关状态的其他信息。
[scanData,status,statustext] = receive(laserSub,10);
现在,您可以订阅者 laserSub 及其关联节点。
clear laserSub clear detectNode
3.2 使用回调函数订阅
您可以指定在收到新消息时调用的函数,而不是使用 receive
来获取数据。这样,其他 MATLAB 代码就可以在订阅者等待新消息时执行。如果要使用多个订阅者,回调是必不可少的。
使用回调函数 exampleHelperROS2PoseCallback
订阅 /pose
主题,该函数将收到的消息作为输入。在主工作区和回调函数之间共享数据的一种方法是使用全局变量。定义两个全局变量 pos
和 orient
。
controlNode = ros2node("/base_station"); pause(5) poseSub = ros2subscriber(controlNode,"/pose",@exampleHelperROS2PoseCallback); global pos global orient
当 /pose
主题收到新的信息数据时,全局变量 pos
和 orient
将被分配到 exampleHelperROS2PoseCallback
函数中。
function exampleHelperROS2PoseCallback(message) % Declare global variables to store position and orientation global pos global orient % Extract position and orientation from the ROS message and assign the % data to the global variables. pos = [message.linear.x message.linear.y message.linear.z]; orient = [message.angular.x message.angular.y message.angular.z]; end
稍等片刻,等待网络发布另一条 /pose
消息。显示更新后的值。
pause(3) disp(pos)
0.0415 -0.0010 -0.0016
disp(orient)
-0.0043 -0.0205 0.0338
如果在命令行中多次输入 pos
和 orient
,就能看到数值在不断更新。
通过清除订阅者变量来停止姿势订阅者
clear poseSub clear controlNode
注:除使用全局外,还有其他方法从回调函数中提取信息。例如,可以将句柄对象作为附加参数传递给回调函数。有关定义回调函数的更多信息,请参阅为图形对象创建回调函数文档。
3.3 发布消息
创建一个向 /chatter
主题发送 ROS 2 字符串信息的发布器。
chatterPub = ros2publisher(node_1,"/chatter","std_msgs/String");
创建并填充 ROS 2 消息,发送到 /chatter
主题。
chatterMsg = ros2message(chatterPub); chatterMsg.data = 'hello world';
ros2 topic list
/chatter /parameter_events /pose /rosout /scan
exampleHelperROS2ChatterCallback
会在收到新消息时被调用,并显示消息中的字符串内容。
chatterSub = ros2subscriber(node_2,"/chatter",@exampleHelperROS2ChatterCallback)
chatterSub = ros2subscriber - 属性: TopicName: '/chatter' LatestMessage: [] MessageType: 'std_msgs/String' NewMessageFcn: @exampleHelperROS2ChatterCallback History: 'keeplast' Depth: 10 Reliability: 'reliable' Durability: 'volatile'
向 /chatter
话题发布一条消息。观察订阅者回调显示的字符串。
send(chatterPub,chatterMsg) pause(3)
当订阅者收到字符串消息时,exampleHelperROS2ChatterCallback
函数被调用。
3.4 断开 ROS 2 网络连接
从 ROS 2 网络中删除样本节点、发布者和订阅者。同时清除全局变量 pos 和 orient
clear global pos orient clear
该处使用的url网络请求的数据。