在MATLAB命令行执行ros2node 和 ros2subscriber后,执行ros2 topic list,MATLAB卡死
提问
setenv(‘ROS_DOMAIN_ID’,‘5’)
node = ros2node(“test_node”);
sub = ros2subscriber(node, “/topic_state”, “pid_interfaces/Command”);
我执行上面的命令,都是正常的,直到紧接着执行下面的命令:
ros2 topic list
然后MATLAB就一直处于busy。 无法完成。 这是为什么?
回答
你现在遇到的是一个MATLAB 在调用 ROS 2 相关 API 时陷入卡死(busy 状态)的问题,这类问题通常与 DDS 通信层阻塞或冲突 有关,下面是针对你情况的深度分析:
🧠 现象分析:
你成功执行了:
setenv('ROS_DOMAIN_ID','5');
node = ros2node("test_node");
sub = ros2subscriber(node, "/topic_state", "pid_interfaces/Command");
然后一旦执行:
ros2 topic list
MATLAB 卡住,进入
busy
,甚至必须强制终止。
✅ 初步结论:
这是一个 DDS 节点/发现层阻塞死锁或资源竞争 问题。
✔ 为什么会这样?
-
ros2node
和ros2subscriber
都会初始化 ROS 2 runtime 和底层 DDS 实例(Fast DDS) -
ros2 topic list
调用又试图初始化 另一个节点或访问 ROS graph -
如果:
- DDS participant 互相冲突(共享资源)
- 底层 DDS 实现(如 FastDDS)有线程死锁风险
- 自定义消息未正确定义或未注册(特别是
pid_interfaces/Command
) - 端口/资源(如 multicast 地址)已被占用或绑定异常
那么在调用ros2 topic list
时,DDS discovery 阶段就会阻塞,造成 MATLAB 卡死
✅ 对策建议:
✅ 一:避免混用 ros2subscriber
和 ros2 topic list
你已经创建了一个 ros2node
和 ros2subscriber
,这些已经启动了一个 DDS 会话。
此时不要再用 ros2 topic list
命令去触发另一个 DDS Graph API 操作,建议调试过程只使用一类 API,否则会出现 DDS 死锁。
❗️推荐做法是:先用
ros2 topic list
,再构建ros2subscriber
✅ 二:换一种方式验证话题是否收到
比如你已经建立了 subscriber,那就直接:
msg = receive(sub, 5);
- 如果 5 秒内能收到消息,说明连接一切正常
- 如果 5 秒后报超时(
Timeout while receiving
),说明订阅建立但没有实际收到消息(要么发太慢,要么消息类型不匹配)
✅ 三:建议你执行以下测试脚本
把下面的操作流程当作“黄金验证路径”,只使用一次 DDS 初始化,避免混用 MATLAB API 和 CLI 命令:
% 确保环境变量设置正确
setenv('ROS_DOMAIN_ID','5');% 创建节点
node = ros2node("sim_debug");% 列出话题(推荐先做这个)
disp(ros2topic("list")); % 如果这里不卡死,说明 DDS OK% 创建订阅者
sub = ros2subscriber(node, "/topic_state", "pid_interfaces/Command");% 接收消息
msg = receive(sub, 5);
disp(msg);
✅ 四:防止卡死建议
如果你已经卡死过,建议你执行以下清理动作后重试:
-
重启 MATLAB
-
关闭所有后台的
ros2 daemon
(Linux 端执行ros2 daemon stop
) -
删除 DDS 缓存:
- Windows:
%LocalAppData%\Temp\fastrtps*
等缓存文件 - Linux:
~/.ros
或~/.dds
相关缓存
- Windows:
-
确保 Linux 和 Windows 使用相同的 RMW 实现(如都是
rmw_fastrtps_cpp
) -
确保 Windows 防火墙彻底关闭,或者明确放通 UDP 多播端口(7400/7410)
✅ 五:参考已知问题
- MathWorks 已知问题报告
- 官方建议在某些版本中避免在 node active 时使用 ros2 CLI 命令
- 或者通过
clear all
清除所有 ROS 节点,再执行ros2 topic list
也可避免冲突
✅ 总结
结论 | 说明 |
---|---|
不建议在已有 ros2node 和 ros2subscriber 的会话中使用 ros2 topic list | 会触发 DDS 层冲突或阻塞 |
建议先使用 ros2 topic list ,再初始化节点/订阅者 | 避免 DDS 冲突 |
你当前问题极可能是 DDS participant 重复或线程资源死锁 | 并非 Simulink 问题,而是底层通信资源未正确释放 |
是否需要我帮你写个自动化测试脚本(自动初始化节点、订阅、接收并打印消息),方便你以后排查这类问题?
继续提问
为什么使用了
setenv(‘ROS_DOMAIN_ID’,‘5’)
node = ros2node(“test_node”);
sub = ros2subscriber(node, “/topic_state”, “pid_interfaces/Command”);
以后,连打开simulink都变得很慢?如何取消节点?
回答
你发现 使用了 ros2node
和 ros2subscriber
后,连打开 Simulink 都变得很慢,这个现象确实存在,并且是可以解释的:
🧠 问题根源:ROS 2 节点阻塞 DDS 网络线程资源
执行:
setenv('ROS_DOMAIN_ID','5')
node = ros2node("test_node");
sub = ros2subscriber(node, "/topic_state", "pid_interfaces/Command");
实际上会常驻启动一个 ROS 2 节点,这个节点:
- 会开启底层 DDS participant(Fast DDS)
- 会占用线程、UDP端口、多播资源
- 会持续尝试“发现”远程参与者,尤其如果远端不回应,就会不断重试,消耗 CPU + 网络堆栈资源
于是就导致:
现象 | 原因 |
---|---|
Simulink 打开慢 | Simulink 在启动时也会尝试初始化 ROS 2 子系统,结果被当前 DDS participant 阻塞 |
MATLAB 运行慢 | ROS2 节点内部有 I/O 线程和 discovery loop,持续占资源 |
多次运行 ros2node 后卡死 | participant 没有及时释放,堆积成“幽灵节点” |
✅ 如何释放和取消节点
你可以使用下面命令立即释放所有 ROS 2 资源:
clear node sub
如果你还用了多个变量:
clear all
然后再执行:
ros2 reset
这将彻底清除 MATLAB 当前会话中的所有 ROS 2 DDS participant 和缓存。
✅ 补充推荐操作
如果你已经执行过 ros2node
等命令,建议在打开 Simulink 前先做这两件事:
clear all
ros2 reset
然后再打开 Simulink,速度会明显恢复。
✅ 持久优化建议
1. 养成习惯:测试完 ROS2 后清理资源
clear node sub
ros2 reset
2. 避免在 MATLAB 启动后立即执行多个 ROS2 节点(会拖慢初始化)
3. 如果你调试频繁,可写个“清理小脚本”:
function cleanup_ros2()tryclear all;ros2 reset;disp("✅ 已清理 ROS2 节点和 DDS participant");catchdisp("⚠️ 无 ROS2 节点正在运行");end
end
✅ 总结
你做了什么? | 发生了什么? |
---|---|
执行 ros2node 和 ros2subscriber | 启动 ROS 2 DDS 节点,抢占资源 |
之后打开 Simulink | Simulink 内部初始化 ROS 2,发生阻塞冲突 |
MATLAB 很慢 | DDS participant 没释放,持续发现网络节点 |
如何解决 | clear node sub ,然后 ros2 reset 即可 |
需要我帮你写一个一键测试 + 自动清理的 ROS2 脚本模板吗?这样你每次调试完就不会拖慢 MATLAB 或 Simulink。