![2e9d3f4967f1876c0ede0900fc1f2817.png](https://i-blog.csdnimg.cn/blog_migrate/47ee8b984b6ac88c51083d162a0a9525.jpeg)
1.连接到ros 控制器
SSH到机器人控制器中,启动roscore;
通过使用“setenv”指令设定上述环境变量的值。设定环境变量后,不带参数的调用“rosinit”指令,ROS主控节点的地址被“ROS_MASTER_URI”指定,全局变量的地址由“ROS_IP”或“ROS_HOSTNAME”给定。如果为“rosinit”指令附加参数,那么相应的环境变量值将被更新。代码运行示例:小车 100 笔记本 182
setenv('ROS_MASTER_URI','http://192.168.1.100:11311’)
setenv('ROS_IP','192.168.1.182')
rosinit
不必同时设定ROS_HOSTNAME和ROS_IP的值,如果两者都设定,那么ROS_HOSTNAME拥有优先权。
关闭操作为:
rosshutdown
2.发布和订阅rostopic
2.1 订阅
在matlab内输入rostopic list:
![9e001b3e1875e91aa9d4f14edfea16af.png](https://i-blog.csdnimg.cn/blog_migrate/4383df20dea4ee3e8a550444d0761b9d.png)
使用“rostopic info”指令检查是否有节点发布数据到“/scan”主题,下面的指令显示节点发布数据到“/scan”主题,可以得到激光雷达数据的发布和订阅关系:
rostopic info /scan
使用“rossubscriber”指令订阅“/scan”主
![6270bd74b0f8d9e44c0b70ba3db7ee3a.png](https://i-blog.csdnimg.cn/blog_migrate/00b596635707acb1c2c668237eb9988b.png)
题,如果该主题已经存在于ROS网络中,“rossubscriber”会自动的检测消息类型,你无须指定。代码运行示例:
laser = rossubscriber('/scan')
![469608e9b189336c5de7ba8732cee654.png](https://i-blog.csdnimg.cn/blog_migrate/b35d65b616ef4148a8b6756cf268801f.png)
使用“receive”指令等待新消息(第二个参数是超时时间(s)),输出“scandata”包含了接收的数据。代码运行示例:
scandata = receive(laser,10)
![23677b83c709159e7ab0b0b29dbaba5d.png](https://i-blog.csdnimg.cn/blog_migrate/5a0160367de4c4c9d3cbd2d06a4461f6.png)
一些数据类型有与之相关的方便的可视化的方式,对于LaserScan数据,“plot”指令能够绘制曲线图,其中“MaximumRange”指定了曲线的最大值范围。运行示例:
plot(scandata,'MaximumRange',7)
![3c17faf5b36adb3a6a22d92d31c05961.png](https://i-blog.csdnimg.cn/blog_migrate/6782cd3384e8589f7f9fbd98854cd7c4.png)
2.2发布
创建一个发布器,用于发送ROS字符串消息到“/chatter”主题(下回分解)。代码运行示例:
chatterpub = rospublisher('/chatter',rostype.std_msgs_String)
![94df35881f5398c564936e581e881a2d.png](https://i-blog.csdnimg.cn/blog_migrate/ca99211a15f42bbab0372cf41e1b9a16.png)
使用“rostopic list”命令,确认“/chatter”主题在ROS网络中是可用的。代码运行示例:
rostopic list
![de934d6c3b167916fc0ac715d421734d.png](https://i-blog.csdnimg.cn/blog_migrate/5df6bc0d85e815162f2319972e5b27a3.png)
为“/chatter”主题定义一个订阅器:
chattersub = rossubscriber('/chatter')
创建并填充一个ROS消息,用于发送到“chatter”主题:
chattermsg = rosmessage(chatterpub);
chattermsg.Data = 'hello world'
![f2a172810a9143f52de6fb2d8ceeac8b.png](https://i-blog.csdnimg.cn/blog_migrate/aff3c545ac852e4f514369890acd6aad.png)
发布一个消息到“/chatter”主题,观察到字符串被订阅器回调函数显示。
send(chatterpub,chattermsg)
2.3 数据操作
保存和下载消息:
可以保存消息的内容用于后期使用。
从订阅器获得新消息:
posedata = receive(posesub,10) posedata =
ROS Twist message with properties:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 Vector3]
Angular: [1x1 Vector3]
使用MATLAB的“save”函数,保存姿态数据到.mat文件。
save('posedata.mat','posedata')
在重新加载文件到工作空间之前,清除“posedata”变量:
clear posedata
现在可以调用“load”函数载入消息数据,上述“posedata”数据将被载入“messageData”结构中,“posedata”是该结构的数据字段:
messageData = load('posedata.mat') messageData =
posedata: [1x1 Twist]
检查“messageData.posedata”查看消息的内容:
messageData.posedata ans =
ROS Twist message with properties:
MessageType: 'geometry_msgs/Twist'
Linear: [1x1 Vector3]
Angular: [1x1 Vector3]
删除MAT文件的方法如下:
delete('posedata.mat')
2.3.1 激光雷达数据
在机器人学领域,激光扫描仪是常见的传感器,通过创建合适类型的空消息,你可以看到ROS中激光扫描仪的标准消息格式。 使用“rosmessage”创建消息: emptyscan = rosmessage(rostype.sensor_msgs_LaserScan) emptyscan =
ROS LaserScan message with properties:
MessageType: 'sensor_msgs/LaserScan'
Header: [1x1 Header]
AngleMin: 0
AngleMax: 0
AngleIncrement: 0
TimeIncrement: 0
ScanTime: 0
RangeMin: 0
RangeMax: 0
Ranges: [0x1 single]
Intensities: [0x1 single]
读取小车激光雷达的topic 数据:
scandata = receive(scan,10)
![bcd953d1eea284af06d54e216ecd214a.png](https://i-blog.csdnimg.cn/blog_migrate/f07f9073d64becd55397179981ffd0b8.png)
使用“readCartesian”函数,使用者可以获得笛卡尔坐标系下的测量点。
xy = readCartesian(scandata) xy =
![20b9e68bb742fc35ca746b255b114d7f.png](https://i-blog.csdnimg.cn/blog_migrate/a599bdbadc8a2f063715872e406a2ea1.png)
Plot 的效果上文已经提到。plot(scandata,'MaximumRange',5)
![fdabb4aeb74d233242d536c49e0de1f9.png](https://i-blog.csdnimg.cn/blog_migrate/f949d96959a9f134de88c7447892ce20.png)
2.3.2 图像数据
MATLAB为图像消息提供了支持,消息格式总是“sensor_msgs/Image”。 使用“rosmessage”指令创建一个空消息,查看标准的ROS图像消息格式。 emptyimg = rosmessage(rostype.sensor_msgs_Image)
![aaad0e84ba65d343a6621a2ee4b52740.png](https://i-blog.csdnimg.cn/blog_migrate/eb522e6fc97b1d29e538e75677989eb4.png)
读取小车发布的图像topic:
img = rossubscriber('/usb_cam/image_raw')
image_data= receive(img,10)
“image_data”字段存储的是原始的图像数据,在MATLAB中并不能用于直接处理或可视化,用户可以使用“readImage”函数恢复出与MATLAB兼容的图像格式。 imageFormatted = readImage(img); 原始的图像的编码格式为“rgb8”,默认情况下,“readImage”函数返回一个标准的4806403的uint8的格式,用户可以使用“imshow”函数查看图像。
imshow(imageFormatted)
![569e3f9cc4c883ae5648941218ba212b.png](https://i-blog.csdnimg.cn/blog_migrate/e9ada156dfb7ad99f6a54e436141ab34.png)
MATLAB支持所有的ROS图像编码格式,“readImage”函数处理转换图像的复杂工作,除了彩色图像,MATLAB还支持单色图像和深度图像。
压缩:许多ROS系统以压缩的格式传输图像数据,MATLAB提供对这些压缩图像消息的支持。大部分的图像格式都支持压缩图像类型,“16UC1”和“32FC1”编码不支持压缩深度图像,单色和彩色图像编码支持压缩图像类型。
2.3.4 点云
点云可用由机器人领域的多种传感器采集,如LIDARS、Kinect和立体摄像机。ROS中最常用的传输点云的消息类型是“sensor_msgs/PointCloud2”,MATLAB提供了一些专业的函数供用户使用点云数据。小车上未装备有深度相机,暂时拿不到pointcloud2:
读取点云位置:
xyz = readXYZ(ptcloud)
点云数据中的NaN表明一些[x,y,z]的值无效。这是三维传感器的一种伪像,用户可以安全的移除所有的NaN值: xyzvalid = xyz(~isnan(xyz(:,1)),:)
一些点云传感器还给点云中的每个点赋RGB彩色的值,如果这些彩色值存在,用户可以调用“readRGB”恢复彩色数据: rgb = readRGB(ptcloud)
在“scatter3”函数的帮助下,用户可以对点云进行可视化,“scatter3”函数将会自动的提取[x,y,z]坐标值,RGB数据如果存在的话,就会以3D散点图的形式显示。“scatter3”函数忽略所有的值为NaN的[x,y,z]坐标,即使该点的RGB值存在。
scatter3(ptcloud)
![29c65243a65c48d8fb6d49cd94c3b944.png](https://i-blog.csdnimg.cn/blog_migrate/f0161337299d1df337a09db39a6a3621.png)
2.4 访问ROS中的tf变换树
ROS中的“tf”系统保持对多坐标系的跟踪并维护坐标系之间的关系于树型结构中。“tf”被分发,所以在ROS网络中的有关所有坐标系的信息每个节点都可以获得。MATLAB允许用户获得该变换树。本例程将让用户熟悉如何获取坐标系信息、获取坐标系之间的变换关系和在两个坐标系之间点、向量和其它实体的变换。
使用“rostf”函数创建一个新的变换树对象,用户可使用该对象获得所有可用的变换并应用于其他实体。tftree = rostf
![699bb56a50f486fd39504503fd450b99.png](https://i-blog.csdnimg.cn/blog_migrate/0efa71655f37ded8b8aa10cc35401846.png)
用户可以使用“AvailableFrames”属性查看所有可用坐标系的名称:
tftree.AvailableFrames
![d1ce9d1a2d122cb5152203203a6e5ad8.png](https://i-blog.csdnimg.cn/blog_migrate/4f3cc419d07f7ac7b144b2e2d943ada0.png)
可以看到小车导航使用的几个坐标系。
用户可以确认可用变换,任何变换都由ROS消息“geometry_msgs/TransformStamped”描述,包含平移和旋转两个部分。
使用“getTransform”函数,获取描述各个坐标系之间转换关系的信息:
imu_to_base = getTransform(tftree, 'base_imu_link', 'base_footprint')
![d30c93ab93f605c1bbc1ae296ac7a7a0.png](https://i-blog.csdnimg.cn/blog_migrate/9c8b84a2ce6863200dd992d2bf64ab94.png)
imuTobaseTranslation = imu_to_base.Transform.Translation
![fb893171a7222015d66b1bf77149dddf.png](https://i-blog.csdnimg.cn/blog_migrate/683183786d35f6dc5add9e79dece8877.png)
quat = imu_to_base.Transform.Rotation
![49785ab93e68c08001cab39da87f328f.png](https://i-blog.csdnimg.cn/blog_migrate/7d471d65ffa52d62770101bf8cbaf629.png)
imuTobaseRotationAngles = rad2deg(quat2eul([quat.W quat.X quat.Y quat.Z]))
![d62ff2e57614956dd6cdb73fa2f10005.png](https://i-blog.csdnimg.cn/blog_migrate/6f5119c2511f493f44dd2bfcbf3c3227.png)
还支持进行变换和发布,使用方法与ros cmdline相似,需要可以自行查找:
3 simulink中使用ROS
Simulink支持机器人操作系统(ROS),使得用户可用Simulink创建模型在ROS网络中使用。ROS是一个通信布局,允许机器人系统的不同部分以消息的形式交换信息。一个组件通过发布消息到一个话题,例如“/odometry”,其它组件通过订阅该话题接收。
Simulink支持ROS包括Simulink库用于发送和接收指定话题的消息,当用户仿真模型时,Simulink连接到ROS网络,该网络可以运行在Simulink上的机器人,也可以是远程的系统。一旦建立连接,Simulink一直与ROS网络交换消息直到仿真结束。如果安装了嵌入式代码,用户还可以从Simulink模型为单独的ROS组件或者节点生成C++代码。
同样需要在ROS控制器内启动roscore
3.1 发布和订阅
3.1.1 发布
从MATLAB的工具栏,选择“HOME > New > Simulink Model”以打开一个新的Simulink模型。从模型窗口选择“View > Library Browser”以打开Simulink库浏览器,点击“Robotics System Toolbox”选项卡。
![c5c14cceed47b19c3060c0771e8a7339.png](https://i-blog.csdnimg.cn/blog_migrate/7cbb122fcec64ca8231489c4e8296f32.png)
拖放一个“Publish”块到模型中并双击以配置话题和消息的类型。
![ef6a6fb0274aa5f6f6bf3eda377e2d76.png](https://i-blog.csdnimg.cn/blog_migrate/7ddb577e2509f3bd1613afcb8711284f.png)
“Topic source”域选择“Specify your own”,在“Topic”域输入“/location”。
“Message Type”域的右侧,点击“Select...”,将弹出一个窗口,选择“geometry_msgs/Point”并点击“OK”以关闭弹出的窗口。
拖放一个“Blank Message”块到模型中并双击打开。点击“Message type”域旁边的“Select…”并从弹出的查询窗口中选择“geometry_msgs/Point”,最后点击“OK”。
从库浏览器的选择“Simulink > Signal Routing”选项卡,拖放一个“Bus Assignment”块。连接“Blank Message”块的输出端口到“Bus Assignment”块的输入端口,连接“Bus Assignment”块的输出端口到“ROS Publish”块的输入端口:
![8569965d0011199a3737359ee8e080b9.png](https://i-blog.csdnimg.cn/blog_migrate/acac0a304b85f100980189ba17e8da94.png)
![8b86bb129dc2f07f6f636f49469d811d.png](https://i-blog.csdnimg.cn/blog_migrate/1c69bd12b332219d66695ad3daaf898a.png)
从库浏览器的“Simulink > Sources”选项卡,拖放两个“Sine Wave”块到模型中。连接每个“Sine Wave”块的输出端口到“Bus Assignment”块指定的输入端口X和Y。
双击连接到输入端口X的“Sine Wave”块,设置“Phase”参数的值为“-pi/2”并点击“OK”。
![40b2f0178b18cc63a5e22e5085c5c6c5.png](https://i-blog.csdnimg.cn/blog_migrate/09a82d113281e3185ffb1b879064bd2c.png)
运行后,rostopic list:
![c3c838b4a7141818b1c35b12e408698b.png](https://i-blog.csdnimg.cn/blog_migrate/b833d9a98447f0a3598d13cb0400e587.png)
3.1.2 订阅
流程与pub工程相同:
![e66657375a858466eb3346db672e1243.png](https://i-blog.csdnimg.cn/blog_migrate/a7a102e1c74e1c3a1319d09d0c49e1bb.png)
点击“Simulation > Model Configuration Parameters”,在“Solver”面板,设置“Type”为“Fixed-step”,“ Fixed-step size”的值为0.01。
设置仿真停止时间为10.0。
![4d53f2ec1b9ae19d18c5364cce3bf395.png](https://i-blog.csdnimg.cn/blog_migrate/9b930cf2dc75c5f8e937aa52dbe03e70.png)
3.2 从Simulink连接到ROS使能的机器人
3.2.1发送速度指令到机器人
从库浏览器的“Robotics System Toolbox”选项卡,拖放一个“Publisher”会到模型中并双击。设置“Topic source”域到“Select From ROS network”,点击“Topic”域旁边的“Select >>”,选择“/mobile_base/commands/velocity”并点击“OK”,注意,消息类型“geometry_msgs/Twist”是自动设定的。
从库浏览器的“Robotics System Toolbox”选显卡,拖放一个“Blank Message”块到模型中并双击。点击“Message type”旁边的“Select >>”,选择“geometry_msgs/Twist”并点击“OK”。
即我们在ros内使用的cmd_vel 的message类型;
双击“Bus Assignment”块,在右侧列表中选择“??? signal1”并点击“Remove”。在左侧列表,展开“Linear”和“Angular”属性,选择“Linear > X”和“Angular > Z”并点击“Select>>”,点击“OK”关闭块。
增加一个“Constant”块、一个“Gain”块和两个“Slider Gain”块:
![9cb115dc266e2ec9f42c4ecdb1ceafab.png](https://i-blog.csdnimg.cn/blog_migrate/875b4f54b6ed7e757c7f02c4068de27f.png)
根据小车性能设定合理的速度角速度范围:
![ad01cb872287e1f75671e398b0f101db.png](https://i-blog.csdnimg.cn/blog_migrate/f532f68814ef5fff489966bf2ccf577f.png)
注意看住小车别冲出去!!!
3.2.2 从机器人接收定位信息
工程搭建参考订阅ROS topic部分:
Bus selector 可选需要输出的数据:
![5822ebbabb7d05eabb54b0f51a5ea4f0.png](https://i-blog.csdnimg.cn/blog_migrate/4dd960667be74824cb39ad9a3c65b344.jpeg)
![0ba202273ff2ef56624d33ba600540b4.png](https://i-blog.csdnimg.cn/blog_migrate/7f114224ab4db7a3586039e6352eb29e.png)
3.3 代码生成
3.3.1 生成
打开空simulink并找到ros代码生成的例程:
![e15712116cf0c8a0dd16e2bd9ea2bad6.png](https://i-blog.csdnimg.cn/blog_migrate/04d8a1d03555995ff61bf6a9c50ba79f.png)
在配置参数对话框的“Code Generation”面板,设置“System target file”为“ert.tlc”并点击“Apply”。然后,从“Target hardware”选择“Robot Operating System (ROS)”,再次点击“Apply”。观察到“ToolChain”被设置为“Catkin”。
![70f5891d723f708900277b95cf2adb11.png](https://i-blog.csdnimg.cn/blog_migrate/9da3b77aa6a701453b702965b72e440c.png)
在配置参数对话框的“Solver”面板,确保解算机(Solver)的“Type”设置为“Fixed-step”,并设置“Fixed-step size”为0.05。在生成的代码中,“Fixed-step size”定义了实际的时间步进,以秒为单位,用于模型的更新循环(参阅About Model Execution)。该值可以设置更小(如0.001或0.0001),但是本例0.05就已经足够了。
参数配置对话框的“Coder Target”让用户定制生成的C++代码,“Package Information”组包含的信息将会被包含在生成的ROS节点的“package.xml”文件。更改“Maintainer name”为“ROS Example User”。(在上图中)
![899e1e835ee690e781e5060f0af3890a.png](https://i-blog.csdnimg.cn/blog_migrate/4e21ee2dc91c4b5a9e0e77c477d7132a.png)
在MATLAB中,更改当前的文件夹到一个临时的位置,用户拥有写的权限。
(2)代码生成过程,首先准备为仿真准备模型,以确认所有的块都正确初始化。该准备工作需要已经启动有效的ROS主控节点。如果用户想要执行代码生成,选择“Tools > Robot Operating System (ROS) > Configure Network Addresses”,然后设置“ROS Master”和“Node Host”的“Network Address”的值为“Default”。
(3)点击“Code > C/C++ Code > Build Model”,如果用户发现任何有关总线类型不匹配,则关闭模型,从基本MATLAB工作空间中清除所有变量,再重新打开模型。
![1d1683a09e3fb4a5118257610a3dbdf4.png](https://i-blog.csdnimg.cn/blog_migrate/9f7556f09b6fb92f560ab3fb6fd58f0a.png)
报错,待解决 四元数到欧拉角转换不支持代码生成,需要自行编写
![f64ee79f75735e9300f9bb4a01633fe0.png](https://i-blog.csdnimg.cn/blog_migrate/b78f648751a2cdc9f80069bcdcee91a5.png)
![98f1f9accfd2563cd4400d510a475e20.png](https://i-blog.csdnimg.cn/blog_migrate/cc1a787adbdfed0de94d004b16c54628.png)
3.3.2 拷贝
(1)确保用户的宿主系统(包含“RobotController.tgz”和“build_ros_model.sh”文件的系统)拥有SCP客户端,对于Windows系统,下一步假设已经安装了PuTTY SCP客户端(pscp.exe)。
(2)使用SCP转换“RobotController.tgz”和“build_ros_model.sh”到用户的Linux虚拟机上的根目录(用户名是“user”,密码是“password”)。下面是示例的转换指令运行在宿主系统(用虚拟机的IP地址替换指令中的“192.168.1.100”):
如果宿主系统是Windows:
pscp.exe RobotController.tgz build_ros_model.sh user@192.168.1.100:
如果宿主系统是Linux或者Mac OS X
scp RobotController.tgz build_ros_model.sh user@192.168.1.100:
注意:“build_ros_model.sh”文件并不是模型特有的,所以只需被转换一次。
3.3.3 运行
在Linux系统,执行如下的命令以创建一个Catkin工作空间,只需做一次。(如果用户已经有一个Catkin工作空间,可以直接使用该工作空间)。
mkdir -p ~/catkin_ws_simulink/src
cd ~/catkin_ws_simulink/src
catkin_init_workspace
(2)在Linux系统执行如下的指令以解压缩并编译ROS节点
cd ~
./build_ros_model.sh RobotController.tgz ~/catkin_ws_simulink
Matlab-ros 节点操作:
(1)在Ubuntu Linux系统,启动ROS主控节点,如果指令返回错误“roscore”已经存在,那么进行下一步。
roscore &
(2)在宿主系统,根据如下代码启动基于MATLAB的机器人仿真器(参阅2.2从Simulink连接到ROS使能的机器人),该仿真器发布到“/odom”话题。
rosinit('192.168.60.163') % replace with IP address of ROS master
ExampleHelperRobotSimulator
(3)在Ubuntu Linux系统,运行新建立的ROS节点,该节点对从“/odom”话题接收到的新消息作出反应。
~/catkin_ws_simulink/devel/lib/robotcontroller/robotcontroller_node
(4)在Ubuntu Linux系统,打开一个新的终端并使用“rostopic list”和“rosnode info”验证节点是活动的。
(5)在宿主计算机,验证仿真机器人向目标运动(“Desired Position”在模型中由常量指定),一旦机器人到达目的地则停止。当机器人停止,点击“ExampleHelperRobotSimulator”图像窗口上的“Randomize Location”,这将使机器人移动到一个随机的位置,那么机器人从该位置向目的地移动。
![62f1ef2531103d167c7005df579ef5c7.gif](https://i-blog.csdnimg.cn/blog_migrate/876648eb23a811abe340201e1256fe97.gif)