主要内容

使用专门的ROS消息

一些常用的ROS消息以一种需要进行转换的格式存储数据,然后才能用于进一步处理。MATLAB®可以帮助您格式化这些专门的ROS消息,方便使用。在本例中,您将探索如何处理激光扫描、未压缩和压缩图像、点云、相机信息、占用网格和八元地图消息的消息类型。

先决条件:处理基本ROS消息

加载示例消息

加载一些示例消息。这些信息由来自各种机器人传感器的真实和合成数据填充。

负载(“specialROSMessageData.mat”

图像信息

MATLAB提供了对图像消息的支万博1manbetx持,它总是具有消息类型sensor_msgs /形象

使用创建空图像消息rosmessage参阅图像消息的标准ROS格式。

Emptyimg = rosmessage(“sensor_msgs /形象”DataFormat =“结构”
emptyimg =带有字段的结构:MessageType: 'sensor_msgs/Image' Header: [1x1 struct] Height: 0 Width: 0 Encoding: " IsBigendian: 0 Step: 0 Data: [0x1 uint8]

为方便起见,完全填充并存储在img变量从specialROSMessageData.mat

检查图像消息变量img在你的工作空间。图像的大小存储在宽度而且高度属性。中的向量发送实际的图像数据数据财产。

img
img =带有字段的结构:MessageType: 'sensor_msgs/Image'头:[1x1 struct]高度:480宽度:640编码:'rgb8' IsBigendian: 0步骤:1920数据:[921600x1 uint8]

数据属性存储的原始图像数据不能直接用于MATLAB中的处理和可视化。您可以使用rosReadImage函数以与MATLAB兼容的格式检索图像。

imageformatting = rosReadImage(img);

原始图像是rgb8编码。默认情况下,rosReadImage返回标准480 × 640 × 3的图像uint8格式。的方法查看此图像imshow函数。

imshow (imageFormatted)

图中包含一个axes对象。坐标轴对象包含一个image类型的对象。

MATLAB®支万博1manbetx持所有ROS图像编码格式,和rosReadImage处理转换图像数据的复杂性。除了彩色图像,MATLAB还支持单色和深度图像。万博1manbetx

此外,MATLAB提供了rosWriteImage函数使用该函数将MATLAB图像转换为ROS消息。利用彩色阈值对样本图像进行基本目标检测。可视化修改后的图像。

greenPercentage = 100*double(image格式化(:,:,2))./sum(image格式化,3);thresholdImg = 255*uint8(greenPercentage > 35);imshow (thresholdImg)

图中包含一个axes对象。坐标轴对象包含一个image类型的对象。

方法将修改后的映像写入ROS消息rosWriteImage函数。因为修改后的图像只有一个通道,并且是类型的uint8,使用mono8编码。

imageMsg = rosWriteImage(emptyimg, thresholdigg,Encoding=“mono8”);

压缩消息

许多ROS系统以压缩格式发送图像数据。MATLAB提供了对这些压缩图像万博1manbetx消息的支持。

使用创建一个空的压缩图像消息rosmessage.ROS中的压缩映像具有消息类型sensor_msgs / CompressedImage有一个标准的结构。

Emptyimgcomp = rosmessage(“sensor_msgs / CompressedImage”DataFormat =“结构”
emptyimgcomp =带有字段的结构:MessageType: 'sensor_msgs/ compres沉积物'报头:[1x1 struct]格式:" Data: [0x1 uint8]

为方便起见,从已填充的压缩图像消息加载specialROSMessageData.mat

检查imgcomp被摄像头捕捉到的变量。的格式属性捕获MATLAB解压存储在其中的图像数据所需的所有信息数据

imgcomp
imgcomp =带有字段的结构:MessageType: 'sensor_msgs/ compres沉积物'头文件:[1x1 struct]格式:'bgr8;jpeg压缩bgr8'数据:[30376x1 uint8]

类似于图片消息,您可以使用rosReadImage以获取标准RGB格式的图像。尽管这个压缩图像的原始编码是bgr8rosReadImage进行转换。

compressed格式化= rosReadImage(imgcomp);

可视化图像使用imshow函数。

imshow (compressedFormatted)

图中包含一个axes对象。坐标轴对象包含一个image类型的对象。

对于压缩图像消息类型,支持大多数图像格式。万博1manbetx的16 uc1而且32 fc1压缩深度图像不支持编码。万博1manbetx支持单色和彩色图像编码。万博1manbetx

点云

点云可以被机器人中使用的各种传感器捕获,包括激光雷达、Kinect®和立体摄像机。ROS中用于传输点云的最常见的消息类型是sensor_msgs / PointCloud2MATLAB为你提供了一些专门的函数来处理这些数据。

您可以通过创建一个空的点云消息来查看点云消息的标准ROS格式。

Emptyptcloud = rosmessage(“sensor_msgs / PointCloud2”DataFormat =“结构”
emptyptcloud =带有字段的结构:MessageType: 'sensor_msgs/PointCloud2' Header: [1x1 struct] Height: 0 Width: 0 Fields: [0x1 struct] IsBigendian: 0 PointStep: 0 RowStep: 0 Data: [0x1 uint8] isdensity: 0

控件中存储的填充点云消息ptcloud变量在您的工作空间:

ptcloud
ptcloud =带有字段的结构:MessageType: 'sensor_msgs/PointCloud2' Header: [1x1 struct]高度:480宽度:640字段:[4x1 struct] IsBigendian: 0 PointStep: 32 RowStep: 20480 Data: [9830400x1 uint8] is高密度:0

点云信息编码在数据属性。您可以提取xyz坐标作为N-by-3矩阵调用rosReadXYZ函数。

rosReadXYZ(ptcloud)
xyz =307200x3单矩阵南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南南

在点云数据中表明了一些xyz值无效。这是一个Kinect®传感器的神器,你可以安全地删除所有值。

xyzValid = xyz(~isnan(:,1)),:)
xyzValid =193359x3单矩阵0.1378 -0.6705 0.1409 -0.6705 1.6260 0.1433 -0.6672 1.6180 0.1464 -0.6672 1.6180 0.1502 -0.6705 1.6260 0.1526 -0.6672 1.6180 0.1556 -0.6672 1.6180 0.1587 -0.6672 1.6180 0.1618 -0.6672 1.6180 0.1649 -0.6672 1.6180

一些点云传感器还为点云中的每个点分配RGB颜色值。如果这些颜色值存在,可以通过调用来检索它们rosReadRGB

rgb = rosReadRGB(ptcloud)
rgb =307200×30.8392 0.7059 0.5255 0.8392 0.7059 0.5255 0.8392 0.7137 0.5333 0.8392 0.7216 0.5451 0.8431 0.7137 0.5529 0.8431 0.7098 0.5569 0.8471 0.7137 0.5569 0.8549 0.7098 0.5569 0.8588 0.7137 0.5529 0.8627 0.7137 0.5490

你可以用rosPlot函数。rosPlot自动提取xyz坐标和RGB颜色值(如果它们存在),并在3d散点图中显示它们。的rosPlot函数忽略所有xyz坐标,即使该点存在RGB值。

rosPlot (ptcloud)

图中包含一个axes对象。标题为Point Cloud的axis对象包含一个类型为scatter的对象。

方法检查点云消息中的所有存储字段rosReadAllFieldNames函数。加载的点云消息包含四个字段xyz,rgb

fieldNames = rosReadAllFieldNames(ptcloud)
字段名=1 x4单元格{'x'} {'y'} {'z'} {'rgb'}

方法可以访问任何字段的相应数据rosReadField函数。您必须手动解包返回的数据,这取决于数据的格式化方式。例如,可以通过对数据的类型转换来提取RGB图像uint8重塑结果。的结果rosReadAllFieldNames用于输入验证的函数。

如果任何(包含字段名,“rgb”) rawData = typeecast (rosReadField(ptcloud,“rgb”),“uint8”);tmp =重塑(permute(重塑(rawData,4,[]),[3,2,1]),ptcloud.Width,ptcloud.Height,4);pcImg = permute(tmp(:,:,[3,2,1]),[2 1 3]);imshow (pcImg)结束

图中包含一个axes对象。坐标轴对象包含一个image类型的对象。

Octomap消息

ROS使用Octomap消息实现3D占用网格。八幅图信息通常用于机器人应用,如3D导航您可以通过创建适当类型的空消息来查看octomap消息的标准ROS格式。

使用rosmessage来创建消息。

Emptyoctomap = rosmessage(“octomap_msgs / Octomap”DataFormat =“结构”
emptyoctomap =带有字段的结构:MessageType: 'octomap_msgs/Octomap' Header: [1x1 struct] Binary: 0 Id: " Resolution: 0 Data: [0x1 int8]

为方便起见,octomap对象中完全填充并存储在octomap载入的变量specialROSMessageData.mat。

检查变量octomap在你的工作空间。的数据字段包含序列化格式的octomap结构。

octomap
octomap =带有字段的结构:MessageType: 'octomap_msgs/Octomap'头文件:[1x1 struct]二进制文件:1 Id: 'OcTree'分辨率:0.0250 Data: [3926x1 int8]

创建一个occupancyMap3D(导航工具箱)对象从ROS消息中获取rosReadOccupancyMap3D函数。控件显示3D占用地图显示函数。

occuancymap3dobj = rosreadoccuancymap3d (octomap);显示(occupancyMap3DObj)

图中包含一个axes对象。标题为Occupancy Map的axis对象包含一个类型为patch的对象。

四元数信息

四元数在机器人技术中常用来表示方向。使用rosmessage创建一个四元数消息并观察字段。

Emptyquatmsg = rosmessage(“geometry_msgs /四元数”DataFormat =“结构”
emptyquatmsg =带有字段的结构:message: 'geometry_msgs/Quaternion' X: 0 Y: 0 Z: 0 W: 0

为了方便起见,从加载表示绕z轴90度旋转的四元数消息specialROSMessageData.mat.检查变量quatMsg在你的工作空间。

quatmsg
quatmsg =带有字段的结构:X: 0 Y: 0 Z: 0.7071 W: 0.7071

创建一个四元数对象从ROS消息中获取rosReadQuaternion函数。的四元数对象包含x、y、z和w组件,并提供其他功能,例如旋转一个点。

quat = rosReadQuaternion(quatmsg);

在三维空间中定义一个点并旋转它rotatepoint函数。将这两点形象化

cartesianPoint = [1,0,1];cartesianPoint plot3 (cartesianPoint (1) (2), cartesianPoint (3),“波”)举行plot3 ([0; cartesianPoint(1)]、[0;cartesianPoint(2)]、[0;cartesianPoint (3)),“k”) rotationResult = rotatepoint(quat,cartesianPoint);rotationResult plot3 (rotationResult (1) (2), rotationResult (3),“罗”) plot3 ([0; rotationResult(1)]、[0;rotationResult(2)]、[0;rotationResult (3)),“k”)包含(“x”) ylabel (“y”) zlabel (“z”网格)

图中包含一个axes对象。axis对象包含4个line类型的对象。

相机信息信息

摄像机标定是机器人视觉应用中常用的一种方法。ROS提供sensor_msgs / CameraInfo发布校准信息的消息类型。使用rosmessage创建一个相机信息消息并观察字段。

Emptycamerainfomsg = rosmessage(“sensor_msgs / CameraInfo”DataFormat =“结构”
emptycamerainfomsg =带有字段的结构:MessageType: 'sensor_msgs/CameraInfo' Header: [1x1 struct]高度:0宽度:0失真模型:" D: [0x1 double] K: [9x1 double] R: [9x1 double] P: [12x1 double] BinningX: 0 BinningY: 0 Roi: [1x1 struct]

值得注意的是,消息存储矩阵K而且P向量。ROS要求以行主格式存储这些矩阵。MATLAB以列为主存储矩阵,因此提取K而且P矩阵需要重塑和换位。

estimateCameraParameters(计算机视觉工具箱)函数可以用来创建cameraParameters(计算机视觉工具箱)而且stereoParameters(计算机视觉工具箱)对象。你可以创建sensor_msgs / CameraInfo的消息来自这些对象rosWriteCameraInfo函数。使用前必须将对象转换为结构。加载摄像机标定结构。

负载(“calibrationStructs.mat”

为方便起见,变量参数个数加载自calibrationStructs.mat是一个人口充足的cameraParameters结构体。写cameraParametersstruct到新的ROS消息rosWriteCameraInfo函数。

msg = rosWriteCameraInfo(emptycamerainfomsg,params);

下表显示了cameraparparameters对象和ROS消息之间的对应关系。

exampleHelperShowCameraParametersTable
ans =5×2表ROS消息相机参数  ___________ ______________________ 内在矩阵“K”“IntrinsicMatrix径向畸变“D”(1:2)切向失真D(3:5)"TangentialDistortion" Height" Height" ImageSize(1)"宽度"Width" "ImageSize(2)"

验证ROS消息的内禀矩阵与的内禀矩阵匹配参数个数

K =重塑(msg.K,3,3)'
K =3×3714.1885 0 563.6481 0 710.3785 355.7254 00 1.0000
intrinsicMatrix = params。IntrinsicMatrix”
intrinsicMatrix =3×3714.1885 0 563.6481 0 710.3785 355.7254 00 1.0000

为方便起见,变量stereoParams加载自calibrationStructs.mat是一个人口充足的stereoParameters结构体。写stereoParametersstruct转换为两个新的ROS消息rosWriteCameraInfo函数。

[ms1, ms2] = rosWriteCameraInfo(msg, steroparams);

下表显示了立体参数对象和ROS消息之间的对应关系。

exampleHelperShowStereoParametersTable
ans =2×2表ROS消息stereoParameters  ____________ ___________________________ 翻译的照相机2 P(: 1:2)”“TranslationOfCamera2(1:2)”摄像头2旋转inv(R1)*R2" "摄像头2旋转"

验证相机2旋转矩阵的ROS消息和stereoParams匹配。

R1 =重塑(msg1.R,3,3)';R2 =重塑(msg2.R,3,3)';R = r1 \ r2
R =3×31.000 -0.0002 -0.0050 0.0002 1.000 -0.0037 0.0050 0.0037 1.000
rotationOfCamera2 = stereo oparams。RotationOfCamera2
rotationOfCamera2 =3×31.000 -0.0002 -0.0050 0.0002 1.000 -0.0037 0.0050 0.0037 1.000

验证摄像头2的ROS信息和平移向量stereoParams匹配。

P =重塑(msg2.P,4,3)';P(1:2)”
ans =1×2-119.8720 - -0.4005
translate of camera2 (1:2)
translationOfCamera2 =1×2-119.8720 - -0.4005

激光扫描信息

激光扫描仪是机器人技术中常用的传感器。ROS提供sensor_msgs /提升发布激光扫描消息的消息类型。使用rosmessage创建一个激光扫描消息并观察字段。

Emptyscan = rosmessage(“sensor_msgs /提升”“DataFormat”“结构”
emptyscan =带有字段的结构:MessageType: 'sensor_msgs/LaserScan' Header: [1x1 struct] AngleMin: 0 AngleMax: 0 AngleIncrement: 0 TimeIncrement: 0 ScanTime: 0 RangeMin: 0 RangeMax: 0 Ranges: [0x1 single]强度:[0x1 single]

既然你创建了一条空消息,emptyscan不包含任何有意义的数据。为方便起见,完全填充的激光扫描消息存储在扫描变量已从specialROSMessageData.mat

检查扫描变量。消息中的主要数据位于范围财产。的数据范围是一个以小角度增量记录的障碍物距离向量。

扫描
扫描=带有字段的结构:MessageType: 'sensor_msgs/LaserScan' Header: [1x1 struct] AngleMin: -0.5467 AngleMax: 0.5467 AngleIncrement: 0.0017 TimeIncrement: 0 ScanTime: 0.0330 RangeMin: 0.4500 RangeMax: 10 Ranges: [640x1 single]强度:[0x1 single]

可以从ROS消息中获取扫描角度rosReadScanAngles函数。在极坐标中可视化扫描数据polarPlot函数。

角度= rosReadScanAngles(扫描);图极坐标(角度,scan.Ranges,LineWidth=2)“激光扫描”

图中包含一个axes对象。axis对象包含一个类型为line的对象。

可以在笛卡尔坐标中得到测量点rosReadCartesian函数。

xy = rosReadCartesian(扫描);

这个填充xy列出了(x, y)坐标是根据所有有效的距离读数计算出来的。方法可视化扫描消息rosPlot功能:

rosPlot(扫描,“MaximumRange”5)

图中包含一个axes对象。标题为Laser Scan的axis对象包含一个类型为line的对象。

创建一个lidarScan对象从ROS消息中获取rosReadLidarScan函数。的lidarScan对象包含范围、角度和笛卡尔点,并提供附加功能,如转换扫描点。使用transformScan函数旋转扫描点并使其可视化情节

lidarScanObj = rosReadLidarScan(扫描)
lidarScanObj = lidarScan with properties:范围:[640x1 double]角度:[640x1 double]直角坐标:[640x2 double]计数:640
rotateScan = transformScan(lidarScanObj,[0,0,pi/2]);情节(rotateScan)

图中包含一个axes对象。标题为LiDAR Scan的axis对象包含一个类型为line的对象。

占用网格消息

占用网格消息通常用于机器人的2D导航应用ROS提供nav_msgs / OccupancyGrid发布激光扫描消息的消息类型。使用rosmessage创建占用网格消息并观察字段。

emptyMap = rosmessage(“nav_msgs / OccupancyGrid”DataFormat =“结构”
emptyMap =带有字段的结构:MessageType: 'nav_msgs/OccupancyGrid'头:[1x1 struct]信息:[1x1 struct]数据:[0x1 int8]

请注意,emptyMap不包含任何有意义的数据。为方便起见,一个完全填充的占用网格消息存储在mapMsg载入的变量specialROSMessageData.mat。

检查mapMsg变量。占用网格值编码在数据字段。

mapMsg
mapMsg =带有字段的结构:MessageType: 'nav_msgs/OccupancyGrid'头:[1x1 struct]信息:[1x1 struct]数据:[251001x1 int8]

使用rosReadOccupancyGrid函数将ROS消息转换为occupancyMap(导航工具箱)对象。使用显示函数显示占用网格。

;;;;;;;显示(occupancyMapObj);

图中包含一个axes对象。标题为Occupancy Grid的axis对象包含一个类型为image的对象。

您可以使用occupancyMap(导航工具箱)对象函数来操作占用网格。使用膨胀扩大占领区域的功能。方法将occuancymap对象写入新的ROS消息rosWriteOccupancyGrid函数。使用显示函数显示新的占用网格。

inflation (occuancymapinflatedmsg,5) = roswriteoccuancymapinflatedmsg (mapMsg, occuancymapobj);显示(occupancyMapObj);

图中包含一个axes对象。标题为Occupancy Grid的axis对象包含一个类型为image的对象。

或者,您也可以创建binaryOccupancyMap(导航工具箱)对象从ROS占用网格消息中获取rosReadBinaryOccupancyGrid函数。的离散占用值01在每个单元格中,而占用率图保存的概率占用率值范围为0而且1在每个单元格。使用显示函数显示二进制占用网格。

binaryMapObj = rosreadbinaryoccuancygrid (mapMsg);显示(binaryMapObj);

图中包含一个axes对象。标题为二进制占用网格的axis对象包含一个类型为image的对象。

类似地,您可以使用binaryOccupancyMap(导航工具箱)对象函数来操作二进制占用网格。使用膨胀函数来改变二进制占用网格并创建一个新的ROS消息rosWriteBinaryOccupancyGrid函数。使用显示函数显示新的二元占用网格。

膨胀(binaryMapObj,5) binaryMapInflatedMsg = roswritebinaryoccuancygrid (mapMsg,binaryMapObj);显示(binaryMapObj);

图中包含一个axes对象。标题为二进制占用网格的axis对象包含一个类型为image的对象。