0. 简介

在上一章中我们详细介绍了ROS与Matlab链接的基础用法。这一章我们将来学习如何使用Matlab当中的Simulink来完成。Simulink对机器人操作系统(ROS)的支持使我们能够创建与ROS网络一起工作的Simulink模型。ROS是一个通信层,允许机器人系统的不同组件以消息的形式交换信息。组件通过将消息发布到特定的主题(如/odometry)来发送消息。其他组件通过订阅该主题来接收消息。本文内容基于慕羽★大佬文章进行了增删。同时由于Simulink的使用在ROS1和ROS2中没有太多的改动,所以我们就仅对ROS1完成了介绍

对ROS的Simulink支持包括一个Simulink块库,用于为指定的主题发送和接收消息。当您模拟模型时,Simulink连接到ROS网络,该网络可以与Simulink在同一台机器上运行,也可以在远程系统上运行。一旦建立了这个连接,Simulink就会与ROS网络交换消息,直到模拟结束。如果安装了Simulink Coder,还可以从Simulink模型为独立ROS组件或节点生成c++代码

同时ROS1的Simulink和ROS2的Simulink支持不太一样。ROS工具箱不支持Simulink中的以下ROS功能:ROSService服务端、ROS的行为以及TF树。

如果应用程序需要这些特性,就需要使用MATLAB的ROS功能。您可以使用MATLAB编写ROS节点,该节点可以将Service服务端、行为以及TF树作为ROS消息发布到主题。然后,Simulink可以订阅该主题来处理这些消息。在MATLAB中使用以下函数来处理这些特征:

ROS服务服务器:rosservicerosvcserver
ROS动作:rosaction, rosactionclient
转换树:rostf, transform, getTransform

对于ROS 2, Simulink只支持发布订阅这两个功能

要查看Simulink中ROS支持的完整列表,请参见Simulink-ROS

1. 初始化ROS并创立链接

  1. 在终端输入以下命令查看本机地址
ifconfig

在这里插入图片描述

  1. 将本机IP写入到.bashrc文件。打开home文件夹,按Ctrl+h显示隐藏的文件,选择.bashrc并打开打开后在最后加入以下命令(后面的IP改为你的电脑的IP),然后保存退出
export ROS_IP=192.168.3.128

在这里插入图片描述

  1. 启动roscore,并获取ROS输出的IP。 在终端输入roscore启动,可以发现此时roscore会输出一个IP如下图所示:
    在这里插入图片描述
  2. 打开MATLAB,建立与ROS的连接。 在MATLAB的命令行窗口输入以下语句,后半部分就是我们上一步得到的ROS输出的IP
setenv('ROS_MASTER_URI','http://jzx-virtual-machine:11311') 
rosinit

在这里插入图片描述

2. 创建一个Publisher

配置一个block,并向/location的节点发送一条geometry_msgs/Point类型的消息。需要做到以下几个步骤

  1. 在MATLAB工具条中,选择Home>Simulink来打开Simulink的起始页。
  2. 在Simulink开始页,单击空白模型创建并打开一个新的Simulink模型。
  3. 在Simulink工具条中,选择Simulation > Library Browser打开Simulink库浏览器。单击ROS工具箱选项卡(也可以在MATLAB命令窗口中输入roslib)。选择ROS库。
    在这里插入图片描述
  4. 将Publish块拖到模型中。双击该块以配置主题和消息类型。
  5. 为Topic源选择Specify your own,并在Topic中输入/location。
  6. 单击 Message type后的Select 按钮。将出现一个弹出窗口。选择geometry_msgs/Point,单击OK关闭弹出窗口。
    在这里插入图片描述

    3. 创建一个Message

    创建一个空白ROS消息,并用机器人路径的X和Y位置填充它。然后将更新后的ROS消息发布到ROS网络。

简单介绍一下Blank Message模块的作用:Blank Message模块用指定的消息或服务类型创建一个空白消息。Msg块的输出是一个空白的ROS消息(总线信号)。设置Class参数来选择ROS消息、服务请求和服务响应消息。这里我们使用的是ROS消息(总线信号)。可以使用总线分配块来修改总线信号中的特定字段。总线信号被初始化为零值(接地)。

在这里插入图片描述
具体操作如下:

  1. 在库浏览器中单击ROS工具箱选项卡,或在MATLAB命令行中键入roslib,选择ROS库。
  2. 将Blank Message块拖到模型中。双击该块以打开block的信息。
  3. 单击Message类型框旁边的Select,并从结果弹出窗口中选择geometry_msgs/Twist。
    在这里插入图片描述
  4. 我们想要发布信息还需要Publish模块,双击打开后按下图所示,因为我们是要发布给/turtle1/cmd_vel去控制小乌龟运动,所以这里选择/turtle1/cmd_vel话题
    在这里插入图片描述
  5. 上面的我们提到了Blank Message输出是一个空白的ROS消息(总线信号)我们可以使用总线分配块(Bus Assignment)来修改总线信号中的特定字段。所以我们还需要一个Bus Assignment模块,具体需要选择Simulink > Signal Routing库中拖出一个Bus Assignment模块。
    在这里插入图片描述

  6. 将空白消息块Blank Message的输出端口连接到总线分配块Bus Assignment的总线输入端口。然后将Bus Assignment块的输出端口连接到ROS Publish块的输入端口。双击总线分配块。您应该看到message信息,总线分配块允许总线中的元素被分配新的值。左边的列表框显示了输入总线中的元素。使用选择按钮来选择要分配的元素。使用向上、向下或移除按钮重新排列选择。 这里选择我们需要的X轴线速度和Z轴角速度,按下图所示操作:
    在这里插入图片描述

  7. 按下图所示连接,这里我们将线速度设置为常数10和角速度设定为常数7
    在这里插入图片描述
  8. 同样要把仿真时间改为inf
    在这里插入图片描述
  9. 单击Run开始模拟。Simulink为模型创建了一个专用的ROS节点,并创建了一个与Publish块相对应的ROS发布者。在模拟运行时,在MATLAB命令窗口中输入rosnode list。这列出了ROS网络中所有可用的节点,并包括一个名称为/untitled_81473的节点(模型的名称加上一个随机数,使其具有唯一性)。在模拟运行时,在MATLAB命令窗口中输入rostopic list。这列出了ROS网络中可用的所有主题,其中包括/location。
    在这里插入图片描述

    4. 创建一个订阅者

  10. 从Library Browser中的ROS Toolbox选项卡中,将Subscribe块拖到模型中。双击该块

  11. 在Topic source框中选择Specify your own,在Topic 框中输入“/turtle1/pose”

  12. 单击Message类型框旁边的Select,并从弹出窗口中选择Turtlesim/Pose。
    在这里插入图片描述

  13. Subscribe块输出一个Simulink总线信号,因此您需要从中提取X和Y信号。但是实际上Subscribe模块是一个空模块

  14. 仍然会在 Simulink > Signal Routing选择一个Bus Selector用于接收信号
  15. 添加一个Bus Selector,并将X和Y添加到右侧,然后与subscribe的输出端进行连接。至于订阅话题的另外一个端口,我们可以放置Scope块,来进行记录。
  16. 拖放一个“XY Graph”块到模型中。将“Bus Selector”的输出端口连接到“XY Graph”的输入端口。
    在这里插入图片描述
  17. 做好以上配置后,将simulink仿真时间改为inf,点击运行,并在ubantu上控制海龟移动,可以看到ubuntu上的海龟pose同simulink 中一致

5. 新消息触发响应

对于订阅者而言,我们很多时候仅需要其仅对新消息触发响应,如果根本没有收到任何消息,它将输出一个空白消息

  1. 在模型中,单击并拖动以选择总线选择器块和XY图形块。右键单击所选区域,从selection中选择Create Subsystem。

  2. 将Simulink库中的Simulink > Ports & Subsystems选项卡中,将一个Enable模块拖到新创建的子系统中。

  3. 将Subscribe块的IsNew输出连接到子系统的启用输入,如下图所示。并删除Terminator模块。这样做只有在前一个时间步骤中接收到新消息时,IsNew输出才为真。
    在这里插入图片描述

    6. simulink自动生成ROS代码

    当我们用simulink完成控制程序的搭建后,我们期望下一次可以直接对ROS进行控制,而不是每次都需要启动matlab和simulink,因此我们可以使用simulink的代码生成器,生成ROS代码,生成代码前需要进行如下的设置。

  4. 按下图所示,打开设置,选择Hardware implementation,然后选择Robot Operating System后点击确定。
    在这里插入图片描述
  5. 按下图所示,检查Solver中的Type是否为Fixed-step,注意求解器一定要选离散型
    在这里插入图片描述
  6. 按下图所示,打开Build Model

在这里插入图片描述

  1. 完成后会生成一个sh文件和一个tgz文件
    在这里插入图片描述
  2. 找到以上文件所在的文件夹,右键在终端打开,输入以下指令
./build_ros_model.sh ROStest2.tgz ~/catkin_ws/

在这里插入图片描述

  1. 然后编译代码即可完成和Simulink相同的功能
cd ~/catkin_ws/
catkin_make
catkin_make install

在这里插入图片描述

7. 自定义Message

当我们的 message 消息比较复杂时,通常要用到自定义的 message 消息,MATLAB 2020b以上的版本自带了ROS Toolbox Interface for ROS Custom Messages 工具,如果低于这个版本就需要通过链接ROS Toolbox Interface for ROS Custom Messages 下载

自定义 Message 编译的目录结构,必须是特定的,即有一个文件夹下放 ROS package,该文件夹可以放多个 ROS 包,然后在某个包下放其 ROS message,ROS message 放置该包目录的msg/ 下,服务文件放于该包目录的 srv/ 目录下,这里就是基本的ROS目录,直接看一下目录结构:

all_package/
-test_pkg/
—msg/
—-BodyIMU.msg
—-HQs.msg
—srv/
—-CustomSrv.srv
—package.xml

然后MATLAB 下采用 rosgenmsg 命令来编译msg信息,这是我们的路径
在这里插入图片描述

% 注意,该目录是到大的目录,而不是在包的目录
% folderpath = "./all_package"
folderPath = fullfile(pwd,"custom");
copyfile("example_*_msgs",folderPath);
rosgenmsg(folderpath)
% ros2genmsg(folderPath) %ros2

编译完成后,会在大目录下生成一个 custom文件夹,
Identifying message files in folder ‘C:/Work/custom’.Done.
Removing previous version of Python virtual environment.Done.
Creating a Python virtual environment.Done.
Adding required Python packages to virtual environment.Done.
Copying include folders.Done.
Copying libraries.Done.
Validating message files in folder ‘C:/Work/custom’.Done.
[3/3] Generating MATLAB interfaces for custom message packages… Done.
Running colcon build in folder ‘C:/Work/custom/matlab_msg_gen/win64’.
Build in progress. This may take several minutes…
Build succeeded.build log

ros2 msg list

example_a_msgs/DependsOnB
example_b_msgs/Standalone
example_c_msgs/DependsOnB

matlab 提示,进行下面三个操作后,可以使用addpath将message位置添加到MATLAB路径,并使用savepath保存这些更改。

  1. 编辑javaclasspath.txt,添加以下文件位置作为新行,并保存文件:
    D:\matlabDemo\ros-messages\custom\jar\test_pkg-0.0.0.jar
    
  2. 通过执行以下命令将自定义消息文件夹添加到MATLAB路径:
    addpath('D:\matlabDemo\ros-messages\custom\msggen') 
    savepath
    
    3.重新启动MATLAB并验证您可以使用自定义消息。输入“rosmsg list”,并确保输出包含生成的自定义消息类型。

注意:javaclasspath.txt文件放置于 prefdir 目录,可以在matlab 命令行中输入prefdir命令进行查看。特别特别注意:实践中将javaclasspath.txt放入 prefdir 目录中,通过查相关问题,则可以从快捷方式启动;如果将javaclasspath.txt放入bin/目录下,也就是matlab 的启动目录后,重启matlab 之后,可以查看 msg,不能从快捷方式启动,要从bin/目录下的matlab.exe启动,所以,还是把该文件放到 prefdir 目录下最好。

# 将 javaclasspath.txt 放入 prefdir 目录,通过 rosmsg list 可查找到消息
rosmsg list
# 但是查看具体消息内容时会报错
rosmsg show test_pkg/BodyIMU

8. 参考链接

https://ww2.mathworks.cn/help/ros/ug/get-started-with-ros-in-simulink.html

https://www.guyuehome.com/35551

https://zhuanlan.zhihu.com/p/403239735

https://blog.csdn.net/weixin_42313598/article/details/105090597

https://zhuanlan.zhihu.com/p/440018329

https://www.youtube.com/watch?v=KPlzSsWWfLE&list=PLn8PRpmsu08p1aZ8t_c8zh4nph2DXRe1R

https://blog.csdn.net/zxf1314ll/article/details/108286970

https://ww2.mathworks.cn/help/ros/ug/ros-custom-message-support.html