目录
一、开始使用 ROS
1.1 ROS 术语
1.2 初始化 ROS 网络
1.3 话题
1.4 服务
1.5 消息
二、连接到 ROS 网络
2.1 在 MATLAB 中创建 ROS 主站
2.2 连接外部 ROS 主站
2.3 节点主机规范
2.4 ROS 环境变量
2.5 验证连接
三、与 ROS 发布者和订阅者交换数据
3.1 订阅和等待消息
3.2 使用回调函数订阅
3.3 发布消息
3.4 关闭 ROS 网络
本示例介绍如何在 MATLAB® 中设置 ROS,并获取有关 ROS 网络和 ROS 消息的信息。
机器人操作系统(ROS)是一种通信接口,可使机器人系统的不同部分相互发现,并在它们之间发送和接收数据。MATLAB® 通过一个函数库支持 ROS,使您能够与支持 ROS 的物理机器人或机器人模拟器(如 Gazebo®)交换数据。
更多信息,请参阅机器人操作系统(ROS)和 ROS 网站上的 "概念 "部分。
使用 rosinit 初始化 ROS。默认情况下,rosinit 会在 MATLAB 中创建一个 ROS 主节点,并启动一个与主节点相连的全局节点。其他 ROS 功能会自动使用全局节点。
rosinit
Launching ROS Core...
.....Done in 5.7786 seconds.
Initializing ROS master on http://172.21.16.85:51063.
Initializing global node /matlab_global_node_13423 with NodeURI http://ah-avijayar:52604/ and MasterURI http://localhost:51063.
使用 rosnode list 查看 ROS 网络中的所有节点。请注意,唯一可用的节点是由 rosinit 创建的全局节点。
rosnode list
/matlab_global_node_13423
使用 exampleHelperROSCreateSampleNetwork 为 ROS 网络添加三个节点以及样本发布者和订阅者。
exampleHelperROSCreateSampleNetwork
再次使用 rosnode list 查看三个新节点(node_1、node_2 和 node_3)。
rosnode list
/matlab_global_node_13423
/node_1
/node_2
/node_3
图中显示了 ROS 网络的当前状态。MATLAB 全局节点是断开的,因为它目前没有任何发布者、订阅者或服务。
使用 rostopic 列表查看 ROS 网络中的可用主题。目前有四个活动主题: /pose、/rosout、/scan 和 /tf。默认主题:rosout 和 tf 始终存在于 ROS 网络中。其他两个主题是作为样本网络的一部分创建的。
rostopic list
/pose
/rosout
/scan
/tf
使用 rostopic info
rostopic info /pose
Type: geometry_msgs/Twist
Publishers:
* /node_1 (http://ah-avijayar:52609/)
Subscribers:
* /node_2 (http://ah-avijayar:52614/)
使用 rosnode info
rosnode info /node_1
Node: [/node_1]
URI: [http://ah-avijayar:52609/]
Publications (3 Active Topics):
* /pose
* /rosout
* /tf
Subscriptions (1 Active Topics):
* /scan
Services (2 Active):
* /node_1/get_loggers
* /node_1/set_logger_level
ROS 服务为跨 ROS 网络的程序调用提供了一种机制。服务客户端向服务服务器发送请求信息,服务服务器会处理请求中的信息并返回响应信息(请参阅 "调用和提供 ROS 服务")。
使用 rosservice list 查看 ROS 网络中所有可用的服务服务器。下面的命令显示,有两个服务(/add 和 /reply)以及所有节点的默认日志记录器服务可用。
rosservice list
/add
/matlab_global_node_13423/get_loggers
/matlab_global_node_13423/set_logger_level
/node_1/get_loggers
/node_1/set_logger_level
/node_2/get_loggers
/node_2/set_logger_level
/node_3/get_loggers
/node_3/set_logger_level
/reply
使用 rosservice info
rosservice info /add
Node: /node_3
URI: rosrpc://ah-avijayar:52618
Type: roscpp_tutorials/TwoInts
Args: MessageType A B
发布者、订阅者和服务使用 ROS 消息来交换信息。每个 ROS 消息都有一个相关的消息类型,它定义了消息中的数据类型和信息布局(请参阅 "使用基本 ROS 消息")。
使用 rostopic type
rostopic type /pose
geometry_msgs/Twist
使用 rosmsg show
rosmsg show geometry_msgs/Twist
% This expresses velocity in free space broken into its Linear and Angular parts.
Vector3 Linear
Vector3 Angular
rosmsg show geometry_msgs/Vector3
% This represents a vector in free space.
% It is only meant to represent a direction. Therefore, it does not
% make sense to apply a translation to it (e.g., when applying a
% generic rigid transformation to a Vector3, tf2 will only apply the
% rotation). If you want your data to be translatable too, use the
% geometry_msgs/Point message instead.
double X
double Y
double Z
使用 rosmsg list 查看 MATLAB 中可用消息类型的完整列表。
1.6 关闭 ROS 网络
使用 exampleHelperROSShutDownSampleNetwork 从 ROS 网络中删除样本节点、发布者和订阅者。只有在先前使用 exampleHelperROSStartSampleNetwork 创建了示例网络时,才需要使用此命令。
exampleHelperROSShutDownSampleNetwork
使用 rosshutdown 关闭 MATLAB 中的 ROS 网络。这将关闭由 rosinit 启动的 ROS 主节点,并删除全局节点。建议在完成 ROS 网络工作后使用 rosshutdown。
rosshutdown
Shutting down global node /matlab_global_node_13423 with NodeURI http://ah-avijayar:52604/ and MasterURI http://localhost:51063.
Shutting down ROS master on http://172.21.16.85:51063.
ROS 网络由一个 ROS 主站和多个 ROS 节点组成。ROS 主节点通过跟踪所有活跃的 ROS 实体,促进 ROS 网络中的通信。每个节点都需要向 ROS 主站注册,才能与网络中的其他节点通信。MATLAB® 可以启动 ROS 主站,也可以在 MATLAB 外部(例如在另一台计算机上)启动主站。
使用 ROS 时,通常需要遵循以下步骤:
本例向您展示了如何
先决条件: 开始使用 ROS
要在 MATLAB 中创建 ROS 主站,请调用 rosinit(不带任何参数)。该函数还创建了全局节点,MATLAB 使用它与 ROS 网络中的其他节点通信。
rosinit
Launching ROS Core...
Done in 0.36647 seconds.
Initializing ROS master on http://172.29.196.158:56952.
Initializing global node /matlab_global_node_23704 with NodeURI http://dcc427349glnxa64:33843/ and MasterURI http://localhost:56952.
MATLAB 外部的 ROS 节点现在可以加入 ROS 网络。它们可以使用 MATLAB 主机的主机名或 IP 地址连接到 MATLAB 中的 ROS 主节点。
您可以通过调用 rosshutdown 关闭 ROS 主节点和全局节点。
rosshutdown
Shutting down global node /matlab_global_node_23704 with NodeURI http://dcc427349glnxa64:33843/ and MasterURI http://localhost:56952.
Shutting down ROS master on http://172.29.196.158:56952.
你也可以使用 rosinit 命令连接外部 ROS 主站(例如运行在机器人或虚拟机上的 ROS 主站)。你可以通过两种方式指定主站的地址:IP 地址或主控程序运行计算机的主机名。
每次调用 rosinit 后,必须先调用 rosshutdown,然后再以不同语法调用 rosinit。为简洁起见,这些示例中省略了对 rosshutdown 的调用。
master_host "是主机名示例,"192.168.1.1 "是外部 ROS 主站的 IP 地址示例。请根据外部主站在网络中的位置调整这些地址。如果在指定地址找不到主控程序,这些命令将失效。
rosinit('192.168.1.1')
rosinit('master_host')
对 rosinit 的两次调用都假定主站接受 11311 端口的网络连接,这是标准的 ROS 主控端口。如果主控程序运行在其他端口上,可以将其指定为第二个参数。要连接到主机名为 master_host、端口为 12000 的 ROS 主站,请使用以下命令:
rosinit('master_host',12000)
如果知道主站的整个统一资源标识符(URI),则可以使用以下语法创建全局节点并连接到主控程序:
rosinit('http://192.168.1.1:12000')
在某些情况下,您的计算机可能连接到多个网络并拥有多个 IP 地址。本图就是一个例子。
左下角的计算机运行 MATLAB,并连接到两个不同的网络。在一个子网中,它的 IP 地址是 73.195.120.50,而在另一个子网中,它的 IP 地址是 192.168.1.100。这台电脑希望连接到 TurtleBot® 电脑上 IP 地址为 192.168.1.1 的 ROS 主站。作为向主节点注册的一部分,MATLAB 全局节点必须指定其他 ROS 节点可以连接到它的 IP 地址或主机名。TurtleBot 上的所有节点都将使用该地址向 MATLAB 全局节点发送数据。
当使用主节点的 IP 地址调用 rosinit 时,它会尝试检测用于联系主节点的网络接口,并将其作为全局节点的 IP 地址。如果自动检测失败,可以在 rosinit 调用中使用 NodeHost 名-值对明确指定 IP 地址或主机名。NodeHost 名-值对可与已显示的任何其他语法一起使用。
这些命令向 ROS 网络公布的计算机 IP 地址为 192.168.1.100。
rosinit('192.168.1.1','NodeHost','192.168.1.100')
rosinit('http://192.168.1.1:11311','NodeHost','192.168.1.100')
rosinit('master_host','NodeHost','192.168.1.100')
一旦某个节点在 ROS 网络中注册,就可以使用命令 rosnode info
在高级使用情况下,您可能希望通过标准 ROS 环境变量来指定 ROS 主节点的地址和您发布的节点地址。前面几节所解释的语法应该足以满足大多数使用情况。
如果没有为 rosinit 提供参数,函数还会检查标准 ROS 环境变量的值。这些变量是 ROS_MASTER_URI、ROS_HOSTNAME 和 ROS_IP。你可以使用 getenv 命令查看它们的当前值:
getenv('ROS_MASTER_URI')
getenv('ROS_HOSTNAME')
getenv('ROS_IP')
你可以使用 setenv 命令设置这些变量。设置完环境变量后,调用不带参数的 rosinit。ROS 主节点的地址由 ROS_MASTER_URI 指定,全局节点的广告地址由 ROS_IP 或 ROS_HOSTNAME 指定。如果为 rosinit 指定了其他参数,它们将覆盖环境变量中的值。
setenv('ROS_MASTER_URI','http://192.168.1.1:11311')
setenv('ROS_IP','192.168.1.100')
rosinit
不必同时设置 ROS_HOSTNAME 和 ROS_IP。如果同时设置,则 ROS_HOSTNAME 优先。
要使 ROS 连接正常工作,必须确保所有节点都能与主节点和节点间进行通信。各个节点必须与主节点通信,以注册订阅者、发布者和服务。它们还必须能够相互通信,以发送和接收数据。如果 ROS 网络设置不当,就有可能出现能发送数据却无法接收数据的情况(反之亦然)。
该图显示了一个 ROS 网络,其中有一个 ROS 主节点和两个向主节点注册的不同节点。每个节点都会联系主节点,查找 ROS 网络中另一个节点的广告地址。一旦每个节点都知道了对方的地址,就可以在没有主节点参与的情况下建立数据交换。
本例展示了如何在 ROS 网络中发布和订阅主题。
ROS 节点交换数据的主要机制是发送和接收消息。消息在主题上传输,每个主题在 ROS 网络中都有一个唯一的名称。如果一个节点想共享信息,它就会使用发布器向话题发送数据。想要接收消息的节点则使用同一主题的订阅者。除了唯一的名称外,每个话题还有一个消息类型,它决定了在该话题下可以传输的消息类型。
这种发布者和订阅者之间的通信具有以下特点:
话题、发布者和订阅者的概念如图所示:
除了如何在 ROS 网络中发布和订阅主题外,本示例还展示了如何
先决条件 开始使用 ROS,连接到 ROS 网络
使用 rosinit 命令在 MATLAB® 中启动 ROS 主程序。
rosinit
Launching ROS Core...
.....Done in 5.4209 seconds.
Initializing ROS master on http://172.21.16.85:56764.
Initializing global node /matlab_global_node_69902 with NodeURI http://ah-avijayar:62300/ and MasterURI http://localhost:56764.
使用提供的辅助函数 exampleHelperROSCreateSampleNetwork,创建一个包含多个发布者和订阅者的 ROS 示例网络。
exampleHelperROSCreateSampleNetwork
使用 rostopic 列表查看有哪些话题。
rostopic list
/pose
/rosout
/scan
/tf
使用 rostopic info 查看是否有节点正在向 /scan 话题发布信息。下面的命令显示 node_3 正在发布该主题。
rostopic info /scan
Type: sensor_msgs/LaserScan
Publishers:
* /node_3 (http://ah-avijayar:62315/)
Subscribers:
* /node_1 (http://ah-avijayar:62305/)
* /node_2 (http://ah-avijayar:62310/)
使用 rossubscriber 订阅 /scan 话题。如果 ROS 网络中已经存在该话题(如此处),rossubscriber 会自动检测其消息类型,因此无需指定。使用 struct 格式的消息可以提高效率。
laser = rossubscriber("/scan","DataFormat","struct");
pause(2)
使用 receive 等待新消息(第二个参数是以秒为单位的超时时间)。(第二个参数是以秒为单位的超时时间。)输出 scandata 包含接收到的消息数据。
scandata = receive(laser,10)
scandata = struct with fields:
MessageType: 'sensor_msgs/LaserScan'
Header: [1×1 struct]
AngleMin: -0.5467
AngleMax: 0.5467
AngleIncrement: 0.0017
TimeIncrement: 0
ScanTime: 0.0330
RangeMin: 0.4500
RangeMax: 10
Ranges: [640×1 single]
Intensities: []
某些消息类型会关联可视化器。对于 LaserScan 消息,rosPlot 会绘制扫描数据。MaximumRange 名 - 值对指定了最大绘图范围。
figure
rosPlot(scandata,"MaximumRange",7)
您可以指定在收到新消息时调用的函数,而不是使用 receive 来获取数据。这样就可以在订阅者等待新消息时执行其他 MATLAB 代码。如果要使用多个订阅者,回调是必不可少的。
使用回调函数 exampleHelperROSPoseCallback 订阅 /pose 话题。
robotpose = rossubscriber("/pose",@exampleHelperROSPoseCallback,"DataFormat","struct")
robotpose =
Subscriber with properties:
TopicName: '/pose'
LatestMessage: []
MessageType: 'geometry_msgs/Twist'
BufferSize: 1
NewMessageFcn: @exampleHelperROSPoseCallback
DataFormat: 'struct'
在主工作区和回调函数之间共享数据的一种方法是使用全局变量。定义两个全局变量 pos 和 orient。
global pos
global orient
当 /pose 话题收到新消息数据时,全局变量 pos 和 orient 将在 exampleHelperROSPoseCallback 函数中分配。
等待几秒钟以确保订阅者可以接收消息。最新的位置和方向数据将始终存储在 pos 和 orient 变量中。
pause(2)
pos
pos = 1×3
-0.0292 -0.0199 -0.0029
orient
orient = 1×3
-0.0270 0.0344 -0.0305
如果在命令行中多次输入 pos 和 orient,就能看到数值在不断更新。
通过清除订阅者变量来停止姿势订阅者
clear robotpose
注:除使用全局外,还有其他方法从回调函数中提取信息。例如,可以将句柄对象作为附加参数传递给回调函数。有关定义回调函数的更多信息,请参阅为图形对象创建回调函数文档。
创建一个向 /chatter 话题发送 ROS 字符串消息的发布器(请参阅 "使用基本 ROS 消息")。
chatterpub = rospublisher("/chatter","std_msgs/String","DataFormat","struct")
chatterpub =
Publisher with properties:
TopicName: '/chatter'
NumSubscribers: 0
IsLatching: 1
MessageType: 'std_msgs/String'
DataFormat: 'struct'
pause(2) % Wait to ensure publisher is registered
创建并填充 ROS 消息,发送到 /chatter 话题。
chattermsg = rosmessage(chatterpub);
chattermsg.Data = 'hello world'
chattermsg = struct with fields:
MessageType: 'std_msgs/String'
Data: 'hello world'
使用 rostopic list 验证 /chatter 话题在 ROS 网络中是否可用。
rostopic list
/chatter
/pose
/rosout
/scan
/tf
为 /chatter 话题定义一个订阅者。exampleHelperROSChatterCallback 在收到新消息时被调用,并显示消息中的字符串内容。
chattersub = rossubscriber("/chatter",@exampleHelperROSChatterCallback,"DataFormat","struct")
chattersub =
Subscriber with properties:
TopicName: '/chatter'
LatestMessage: []
MessageType: 'std_msgs/String'
BufferSize: 1
NewMessageFcn: @exampleHelperROSChatterCallback
DataFormat: 'struct'
向 /chatter 话题发布消息。订阅者回调将显示该字符串。
send(chatterpub,chattermsg)
pause(2)
ans =
'hello world'
一旦您发布了字符串消息,exampleHelperROSChatterCallback 函数就会被调用。
从 ROS 网络中删除样本节点、发布者和订阅者。清除全局变量 pos 和 orient。
exampleHelperROSShutDownSampleNetwork
clear global pos orient
关闭 ROS 主节点并删除全局节点。
rosshutdown
Shutting down global node /matlab_global_node_69902 with NodeURI http://ah-avijayar:62300/ and MasterURI http://localhost:56764.
Shutting down ROS master on http://172.21.16.85:56764.