尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ROS与MATLAB通信实战:从环境配置到Gazebo联合仿真

ROS与MATLAB通信实战:从环境配置到Gazebo联合仿真 做机器人算法验证时我经常要在 ROS 环境里跑感知、规划又想在 MATLAB/Simulink 里快速调参、分析数据。两套工具链各有优势ROS 生态丰富传感器驱动、导航框架、可视化工具基本开箱即用MATLAB 在矩阵运算、控制系统设计、Simulink 建模和数据分析上效率极高。但把它们接到一起很多刚入门的人会卡在环境搭建、消息类型不匹配、网络不通这些细节上。这篇教程把 ROS 与 MATLAB 通信及仿真这条路完整走一遍包含可复制的示例代码、典型报错和排查思路适合正在做机器人仿真、课程设计、算法预研或想用 Simulink 做硬件在环测试的读者。1. 背景与核心概念1.1 ROS 和 MATLAB 各自解决什么问题ROSRobot Operating System机器人操作系统本质是一套分布式通信框架它提供节点之间的话题、服务、参数等通信机制方便多进程、多语言、多主机协作。机器人项目里激光雷达驱动、SLAM、导航、机械臂控制都可以封装成独立节点通过话题传递消息。MATLAB 则是一个数值计算和算法开发环境Simulink 是多域物理建模与仿真平台。它们的强项是快速验证控制算法、处理传感器数据、做可视化分析和自动化测试。尤其在做控制器设计时Simulink 的框图模型比手写 C 更容易调整增益、切换算法、生成代码。1.2 ROS 与 MATLAB 通信解决什么问题两者结合最典型的场景有三种算法快速验证感知或控制算法先用 MATLAB 写出来通过 ROS 接收真实传感器数据验证后再移植到 C。联合仿真Gazebo 或真实机器人运行 ROS 环境MATLAB/Simulink 作为外部节点发送控制指令、接收状态反馈形成闭环。数据采集与分析用 ROS 录制 rosbag再放进 MATLAB 做离线分析、标定和特征提取。这种模式下MATLAB 不是独立软件而是 ROS 网络中的一个普通节点。只是这个节点运行在 Windows、Mac 或 Linux 上通过 ROS 标准协议与其他节点通信。1.3 核心概念扫盲在继续之前需要先理解几个常见词节点Node一个独立进程负责某类功能比如 /cmd_vel 发布节点。话题Topic发布订阅式单向数据流适合高频传感器数据。服务Service请求响应式双向通信适合调用一次、等待结果的逻辑。动作Action带反馈的长时间任务比如导航到目标点。消息Message话题和服务传输的数据结构例如 geometry_msgs/Twist。MATLAB 通过 ROS Toolbox 与 ROS 通信你可以完全不用写 C也能发布和订阅这些消息。Simulink 中甚至有专门的消息收发模块可以直接和 Gazebo、真实机器人联调。2. 环境准备与版本说明2.1 推荐环境组合目前最常见的组合是操作系统Ubuntu 20.04 或 Ubuntu 22.04ROS 版本ROS 1 Noetic 或 ROS 2 HumbleMATLAB 版本R2021a 及以上并安装 ROS Toolbox仿真工具Gazebo或 Gazebo Classic如果你希望在 MATLAB 和 ROS 之间做联合仿真ROS 主机建议是 Ubuntu因为绝大多数机器人驱动、Gazebo 仿真和 ROS 包都在 Linux 下发布。MATLAB 可以装在同一个 Linux 系统里也可以装在 Windows 宿主机上通过网络连接。后者需要保证两端处于同一局域网并正确配置 ROS_MASTER_URI 和 ROS_IP。关于版本支持我建议你以 MATLAB 官网对 ROS Toolbox 的支持矩阵为准不要只凭别人一句话就定版本。比如某些 MATLAB 版本对 ROS 2 Dashing/Foxy/Humble 的支持范围不同升级 ROS 版本后可能导致 ros2genmsg 等工具失效。示例项目里我们以 ROS 1 Noetic 为例如果使用 ROS 2Matlab 侧函数名会变为 ros2init、ros2subscriber、ros2publisher整体思路一致。2.2 安装 ROSUbuntu 20.04 下安装 ROS Noetic官方步骤是设置 sources.list、添加密钥、apt 更新、安装 ros-noetic-desktop-full然后初始化 rosdep 和 environment。如果网络不稳定可以通过国内镜像源安装也可以借助社区经常提到的一键安装脚本比如“鱼香ROS”工具。使用一键脚本前建议先阅读脚本内容确认安装动作符合预期。安装完成后检查环境source /opt/ros/noetic/setup.bash roscore如果能看到started core service [/rosout]说明 ROS 主节点正常启动。2.3 安装 MATLAB ROS Toolbox在 MATLAB 中检查是否已经安装 ROS Toolboxver(ros)如果显示找不到该工具箱可以在 MATLAB 的 Add-On Explorer 中搜索 ROS Toolbox 并安装。需要注意MATLAB 安装包体积大Linux 环境下要确保磁盘空间充足并给 MATLAB 启动脚本matlab添加可执行权限。安装完成后可以在 MATLAB 里运行rosinit它会尝试连接当前环境变量ROS_MASTER_URI指向的 ROS Master。如果本机没有启动 roscore会提示连接失败。2.4 网络配置当 MATLAB 与 ROS 不在同一台机器时网络配置是最容易出错的点。ROS 主机使用hostname -I查看 IP设置export ROS_MASTER_URIhttp://ros主机IP:11311和export ROS_IPros主机IP。MATLAB 主机在连接前设置环境变量或在 MATLAB 中使用rosinit(http://ros主机IP:11311)手动指定 Master 地址。虚拟机场景下建议把网络模式改成桥接Bridged模式否则宿主机和虚拟机之间的 IP 可能不在同一子网连接不稳定。3. ROS 与 MATLAB 通信原理拆解3.1 ROS 通信机制回顾ROS 中最常用的是话题。发布者把消息发到话题上订阅者接收消息。这种模式适合连续数据流比如 /scan 激光数据、/odom 里程计数据、/camera/image_raw 图像数据。服务则适合一次性调用。例如机器人清空地图、切换导航目标点。客户端发送请求服务端返回响应是一问一答的模式。动作是服务的增强版适合需要取消、需要实时反馈的长任务。例如导航到目标点、机械臂执行轨迹。MATLAB ROS Toolbox 对三种方式都有支持话题可以用rospublisher、rossubscriber、send、receive服务可以用rossvcclient动作主要通过rosactionclient实现。3.2 MATLAB 如何成为 ROS 节点调用rosinit后MATLAB 会启动一个内部 ROS 节点并连接到 ROS Master。此时你可以用rostopic list查看当前所有话题这个命令在 MATLAB 命令行里也能执行。rosinit rostopic listrosinit实际上做了什么它会创建一个节点句柄注册到 Master并运行一个后台订阅线程。这样后续rossubscriber能持续接收消息而不会阻塞 MATLAB 主线程。如果你使用 ROS 2对应的初始化函数是ros2init ros2 topic list3.3 MATLAB 发布与订阅的本质MATLAB 发布话题时需要先创建发布者pub rospublisher(/cmd_vel, geometry_msgs/Twist); msg rosmessage(pub); msg.Linear.X 0.2; msg.Angular.Z 0.0; send(pub, msg);这段代码的逻辑是创建一个发布到 /cmd_vel 的发布者然后构造一个 geometry_msgs/Twist 消息设置线速度和角速度最后 send 发布。注意rosmessage(pub)会根据发布者的消息类型自动生成一个空消息结构方便直接赋值。订阅时常见写法有两种。一种是阻塞接收sub rossubscriber(/odom, nav_msgs/Odometry); odomMsg receive(sub, 10);receive会阻塞等待最多 10 秒直到收到消息。另一种是回调函数方式适合持续数据处理sub rossubscriber(/scan, scanCallback);当新消息到达时MATLAB 会自动调用scanCallback函数并把消息对象传进去。3.4 Simulink 中的 ROS 模块Simulink 里也有 ROS 相关模块位于 Simulink Library Browser 的 Robotics System Toolbox 或 ROS Toolbox 分类下。常用模块包括Publish往指定话题发布消息。Subscribe订阅指定话题输出消息内容。Call Service调用 ROS 服务。这些模块适合搭建控制闭环。例如在 Simulink 中读取 /odom 位置信息计算期望速度再通过 Publish 模块发到 /cmd_vel就能形成 Gazebo 中的自动控制回路。Simulink 还可以生成 C 代码编译成独立 ROS 节点不过这一步对编译器版本、ROS 版本和 MATLAB 版本都有要求建议先从外部节点模式开始。4. 完整实战案例下面通过两个完整案例演示 ROS 与 MATLAB 通信和联合仿真的核心流程。4.1 案例一MATLAB 订阅 ROS 话题这个案例中我们先用 Python 写一个 ROS 发布者节点模拟机器人速度数据然后在 MATLAB 里订阅并绘图。4.1.1 创建 ROS 工作区在 Ubuntu 主机上创建功能包mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src catkin_create_pkg ros_matlab_demo rospy std_msgs geometry_msgs cd ~/catkin_ws catkin_make source devel/setup.bash这里我们创建了一个名为 ros_matlab_demo 的功能包依赖 rospy 和消息包。功能包路径为~/catkin_ws/src/ros_matlab_demo。4.1.2 编写 Python 发布节点在~/catkin_ws/src/ros_matlab_demo/scripts/下新建vel_publisher.py#!/usr/bin/env python # -*- coding: utf-8 -*- import rospy from geometry_msgs.msg import Twist def main(): rospy.init_node(matlab_demo_vel_publisher, anonymousTrue) pub rospy.Publisher(/demo_vel, Twist, queue_size10) rate rospy.Rate(10) # 10 Hz vel_msg Twist() vel_msg.linear.x 0.5 vel_msg.angular.z 0.1 while not rospy.is_shutdown(): pub.publish(vel_msg) rate.sleep() if __name__ __main__: try: main() except rospy.ROSInterruptException: pass给脚本添加执行权限chmod x ~/catkin_ws/src/ros_matlab_demo/scripts/vel_publisher.py4.1.3 启动 ROS Master 和发布节点终端一source /opt/ros/noetic/setup.bash roscore终端二source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash rosrun ros_matlab_demo vel_publisher.py可以用rostopic echo /demo_vel验证话题是否有数据持续输出。4.1.4 MATLAB 侧订阅并绘制在 MATLAB 中新建脚本subscribe_demo.mclear; clc; % 连接 ROS Master把 IP 换成你的 ROS 主机 IP rosinit(http://localhost:11311); % 创建订阅者 sub rossubscriber(/demo_vel, geometry_msgs/Twist); % 接收 100 条消息记录线速度 numSamples 100; linearVel zeros(1, numSamples); for i 1:numSamples msg receive(sub, 10); linearVel(i) msg.Linear.X; pause(0.1); end % 绘制线速度时序 figure; plot(linearVel, LineWidth, 1.5); xlabel(Sample); ylabel(Linear Velocity (m/s)); title(MATLAB Subscribed /demo_vel); grid on; % 关闭 ROS 连接 rosshutdown;运行后MATLAB 会画出 100 个采样点上的线速度变化。如果 ROS 节点发布的是固定值 0.5图像会是一条接近 0.5 的水平线。这里有几个关键点rosinit(http://localhost:11311)指定 Master 地址如果是远程主机要写成对应 IP。rossubscriber第三个参数是消息类型这里必须和发布端一致。receive(sub, 10)表示最多等 10 秒超时会报错。4.1.5 结果说明预期结果是 MATLAB 能正常收到来自 Python 节点的 Twist 消息。如果收不到优先检查rostopic list是否能看到 /demo_vel以及两端 ROS_MASTER_URI 配置是否一致。4.2 案例二MATLAB 控制 Gazebo 中的机器人这个案例演示真实联合仿真Gazebo 里运行一个差速驱动机器人MATLAB 发布速度指令并订阅里程计数据形成闭环。4.2.1 启动 Gazebo 仿真环境以 TurtleBot3 为例需要先安装相关功能包。启动命令如下source /opt/ros/noetic/setup.bash export TURTLEBOT3_MODELburger roslaunch turtlebot3_gazebo turtlebot3_world.launch启动后Gazebo 会加载一个包含小车的仿真环境。/cmd_vel话题用于发布速度指令/odom话题用于获取里程计信息。检查话题rostopic list正常情况下可以看到/cmd_vel和/odom。4.2.2 MATLAB 发布速度并订阅里程计新建 MATLAB 脚本gazebo_control_demo.mclear; clc; rosinit(http://localhost:11311); % 发布 /cmd_vel velPub rospublisher(/cmd_vel, geometry_msgs/Twist); velMsg rosmessage(velPub); % 订阅 /odom odomSub rossubscriber(/odom, nav_msgs/Odometry); % 控制参数 simTime 5.0; % 仿真时长 dt 0.1; % 控制周期 steps simTime / dt; % 记录轨迹 x_log zeros(1, steps); y_log zeros(1, steps); for i 1:steps % 读取当前里程计 odomMsg receive(odomSub, 2); x_log(i) odomMsg.Pose.Pose.Position.X; y_log(i) odomMsg.Pose.Pose.Position.Y; % 设定速度先前进后转弯 if i * dt 2.0 velMsg.Linear.X 0.2; velMsg.Angular.Z 0.0; elseif i * dt 3.0 velMsg.Linear.X 0.0; velMsg.Angular.Z 0.5; else velMsg.Linear.X 0.2; velMsg.Angular.Z 0.0; end send(velPub, velMsg); pause(dt); end % 停止机器人 velMsg.Linear.X 0.0; velMsg.Angular.Z 0.0; send(velPub, velMsg); % 绘制轨迹 figure; plot(x_log, y_log, LineWidth, 1.5); xlabel(X (m)); ylabel(Y (m)); title(Robot Trajectory in Gazebo); axis equal; grid on; rosshutdown;运行这个脚本后可以看到 Gazebo 中的小车先直线前进、再左转、再前进MATLAB 中则画出完整的二维轨迹。4.2.3 为什么用 receive 而不是回调在这个脚本里我们使用receive按控制周期主动获取里程计。好处是代码简单逻辑顺序清晰适合固定步长控制。如果使用回调函数消息到达时间与发送指令的循环可能不同步需要借助事件驱动逻辑对新手不够直观。4.2.4 结果说明如果一切正常Gazebo 小车运动轨迹和 MATLAB 绘制的轨迹基本一致。如果轨迹异常或小车不动可以从以下几个方面检查/cmd_vel是否有效在终端运行rostopic echo /cmd_vel看是否有数据。小车是否有电池或控制模式限制仿真环境下一般没有但真实机器人需要注意。里程计是否发布运行rostopic echo /odom检查数据频率。4.3 案例三Simulink 与 ROS 联合仿真除了脚本方式Simulink 也能直接和 ROS 交互。下面是一个最简单的例子用 Simulink 发布正弦波速度指令并订阅 Gazebo 的里程计。4.3.1 创建 Simulink 模型在 MATLAB 命令窗口输入simulink新建空白模型。打开 Library Browser添加以下模块Signal GeneratorSourcesPublishROS ToolboxSubscribeROS ToolboxScopeSinks4.3.2 配置 Publish 和 Subscribe 模块Publish 模块配置Topic/cmd_velMessage typegeometry_msgs/TwistSample time0.1由于 Publish 模块需要 Twist 结构体输入我们可以用一个 Bus Assignment 或 MATLAB Function 模块构造消息。最简单的方法是添加一个 MATLAB Functionfunction twist buildTwist(speed) twist.Linear.X speed; twist.Linear.Y 0; twist.Linear.Z 0; twist.Angular.X 0; twist.Angular.Y 0; twist.Angular.Z 0; end将 Signal Generator 输出连接到这个函数的 speed 输入再把 twist 输出接到 Publish 模块。Subscribe 模块配置Topic/odomMessage typenav_msgs/OdometrySample time0.1Subscribe 模块输出整个 Odometry 消息你可以用 Selector 或 Bus Selector 取出 Position.X 和 Position.Y再连接到 Scope 查看轨迹。4.3.3 运行模型在模型配置中不需要额外设置直接点击 Run。只要 MATLAB 已经rosinitSimulink 就会通过同一个 ROS 网络收发数据。需要注意的是Simulink 模型运行时会占用 MATLAB 主线程如果你还要在命令行执行其他操作会不方便。建议把 Simulink 运行模式设置为外部模式External或者在单独 MATLAB 进程中运行模型。5. 常见问题与排查思路ROS 与 MATLAB 通信过程中高频问题往往集中在网络配置、消息类型、版本兼容三方面。下面用表格汇总。问题现象常见原因解决思路rosinit 报错Connection refusedROS Master 没有启动在 ROS 主机执行 roscore确认 11311 端口rosinit 连接远程 Master 失败ROS_MASTER_URI 指向了 localhost在 MATLAB 中使用rosinit(http://IP:11311)MATLAB 能连接但 receive 超时两端网络隔离或防火墙检查 ros_IP、ping 连通性虚拟机改用桥接模式rostopic list 看不到自定义话题MATLAB 和 ROS 不在同一 ROS 网络确保 ROS_MASTER_URI 一致且都在同一局域网MATLAB 识别不了自定义消息自定义消息还没有生成 MATLAB 接口使用 rosgenmsg 生成消息接口Simulink Publish 模块输入结构不匹配Twist 消息字段不全用 Bus Assignment 或者 MATLAB Function 构造完整结构体Gazebo 中小车不动/cmd_vel 发布频率过低或消息全零检查速度数值和输出频率必要时用 rostopic echo 验证MATLAB 在 Ubuntu 上打开很慢缺少图形驱动或字体渲染问题设置 MATLAB_JAVA或使用软件 OpenGLROS 2 下 rosinit 不可用使用了 ROS 2 环境改用 ros2init、ros2subscriber、ros2publisher5.1 rosinit 连接失败排查步骤在 ROS 主机运行hostname -I查看 IP。检查echo $ROS_MASTER_URI默认应该是http://localhost:11311。在 MATLAB 主机用浏览器或ping测试能否访问该 IP。如果是虚拟机确认网络模式是桥接而不是 NAT。在 MATLAB 中用rosinit(http://192.168.1.100:11311)明确指定 Master 地址。5.2 自定义消息处理当 ROS 工程中有自定义消息比如my_msgs/ControlCmdMATLAB 默认无法直接识别。解决办法是使用 ROS Toolbox 的rosgenmsg函数rosgenmsg(/path/to/catkin_ws/src)执行后MATLAB 会生成对应的消息接口并在当前路径下生成一个matlab_gen文件夹。你需要把该文件夹添加到 MATLAB 路径然后重新rosshutdown和rosinit才能正常使用自定义消息。注意rosgenmsg生成的接口和 ROS 版本强相关。如果以后升级了 ROS 功能包里的消息定义需要重新生成一次否则容易出现字段对不上或类型冲突。6. 最佳实践与工程建议6.1 版本定好后不要轻易漂移ROS 和 MATLAB 版本都比较“挑剔”。建议在项目里记录一份环境清单包括 Ubuntu 版本、ROS 发行版、Gazebo 版本、MATLAB 版本、ROS Toolbox 版本以及是否使用了 Docker。每次重新部署环境时按照清单复现可以省去大量排错时间。6.2 网络配置固定化在联合仿真实战里最好把 ROS 主机和 MATLAB 主机的 IP 固定下来。DHCP 可能导致 IP 漂移rosinit 和 roslaunch 配置里写死的地址会失效。你可以在 Ubuntu 的 Netplan 或 NetworkManager 里配置静态 IP并把两台机器放到同一网段。如果 MATLAB 和 ROS 跑在同一台电脑上问题会简单很多直接用rosinit默认连接 localhost 即可。第一轮学习建议先单机跑通再扩展到远程。6.3 优先使用标准消息类型ROS 已经提供了非常丰富的标准消息比如 geometry_msgs、nav_msgs、sensor_msgs、std_msgs。在设计接口时优先复用这些消息能减少rosgenmsg的额外开销。只有业务逻辑确实需要特殊字段时再定义自定义消息。自定义消息设计上要注意字段命名使用可读性强的下划线风格。单位写清楚比如长度一律用米角度用弧度。增加时间戳字段std_msgs/Header header方便下游同步。6.4 Simulink 联调时注意时间同步Simulink 仿真时间和 ROS 时间默认是独立的。如果你要严格同步比如用 rosbag 录制仿真数据做回放需要配置 Simulink 的 Sample Time 和 ROS 端时间源一致。常见做法是在 Simulink 中使能simulation time与 ROS Clock 同步。对于大多数控制场景真随机延迟有几十毫秒也能接受但如果你在做里程计融合或高精度控制一定要考虑时间戳对齐。6.5 安全边界先仿真再真机用 MATLAB 控制真实机器人前必须先在 Gazebo 中完整验证。原因很简单MATLAB 脚本里一个符号错误可能导致机器人猛冲或反转。真实机器人上应当设置速度上限、使能急停、监控状态反馈。如果你要发布真实机器人的 cmd_vel务必做到在代码里限制最大线速度和角速度。增加 watchdog超过指定时间没有收到新指令就停止。先以极低速度测试比如 0.05 m/s。手动断开急停开关确保随时能停车。6.6 日志与数据回放联合仿真时记录数据非常重要。你可以用 rosbag 记录整个 ROS 网络数据rosbag record -O matlab_demo.bag /cmd_vel /odom然后在 MATLAB 中离线处理这个 bag 文件bag rosbag(matlab_demo.bag); odomSel select(bag, Topic, /odom); odomStruct readMessages(odomSel, DataFormat, struct);这样做的好处是即使仿真环境已经被关闭你仍然可以反复调整算法参数不需要重新跑一遍仿真。6.7 代码组织建议MATLAB 脚本不要全堆在一个文件里。建议按功能拆分模块ros_utils/存放 rosinit、rosshutdown 等连接管理函数。controllers/存放控制算法。plotters/存放数据可视化函数。scripts/存放一次性的演示脚本。这样当你从 MATLAB 迁移到 C 节点时模块边界已经清晰可以直接参考算法部分的输入输出接口。7. 总结与学习路线本文从 ROS 与 MATLAB 通信的原理出发梳理了环境准备、消息类型、话题订阅发布、Simulink 联合仿真等关键内容并给出了三个可运行的实战案例。你现在可以动手做以下练习在 Ubuntu 安装 ROS Noetic在 MATLAB 安装 ROS Toolbox执行一次rosinit。用 Python 编写一个话题发布节点让 MATLAB 订阅并绘图。启动 Gazebo 的 TurtleBot3 仿真用 MATLAB 控制小车走一个方形轨迹。尝试将 PID 控制器放进 Simulink订阅 /odom发布 /cmd_vel形成闭环。继续深入可以学习这些方向ROS 2 与 MATLAB 的 ros2 系列接口。Simulink Coder 自动生成 ROS C 节点。MATLAB 的 Robotics System Toolbox 与运动规划算法。用 rosbag 做数据集采集再用 MATLAB 做感知算法评测。如果你在实战中遇到“版本不兼容”“消息类型不识别”“网络连接失败”这些问题多回到第 5 节的排查表格大概率能快速定位。机器人开发路很长先把 ROS 和 MATLAB 这条通信链路打通后面做感知、规划、控制都会顺手很多。
返回列表