ROS机器人项目(Ucar)故障排查与解决方案文档
引言
本文档全面总结Ucar ROS机器人项目的复杂故障排查过程,涵盖从C++代码逻辑错误、内存管理问题到嵌入式系统(Rockchip主板)图形驱动与ROS网络配置问题的完整解决方案。记录每个问题的症状、根本原因、解决方案及相关指令,形成可供参考的调试经验。
问题一:音频播放失败(“文件未找到”)
症状
节点播放唤醒音或回复音时出现错误:
play FAIL formats: can't open input file '/audio/wakeup.wav': No such file or directory
根本原因
程序代码使用硬编码绝对路径(/audio/wakeup.wav
),系统从文件系统根目录查找,而非ROS功能包相对路径,导致查找失败。
解决方案
修改C++代码,动态获取功能包绝对路径并与音频文件相对路径拼接。
推荐代码实现(以AIUITester.cpp中的process_recv函数为例)
// 1. 包含头文件
#include <ros/package.h>
// 2. 构建完整路径
std::string package_path = ros::package::getPath("speech_command");
if (!package_path.empty()) {
// WAKEUP_RESPONSE_WAV 是Global.h中定义的相对路径 "/audio/wakeup.wav"
std::string wav_path = package_path + WAKEUP_RESPONSE_WAV;
std::string command = "play " + wav_path;
system(command.c_str());
}
问题二:音频播放失败(“无法确定文件类型”)
症状
解决"文件未找到"问题后,出现新错误:
play FAIL formats: can't determine type of file '/home/ucar/ucar_ws/src/speech_command'
根本原因
语音识别结果在offline_QA.txt
配置文件中无完全匹配条目,导致FindDocument()
函数返回空字符串,路径拼接后仅剩功能包路径(目录),程序试图播放目录而非音频文件。
解决方案
数据层面
检查并确保config/offline_QA.txt
包含所有需响应的语音指令,且与程序识别文本(含标点)完全对应。
代码层面
增加代码健壮性,在播放音频前检查文件路径是否为空。
推荐代码实现(aiuiMain.cpp的data_send函数)
string document = FindDocument(question_str);
// 增加路径非空判断
if (!document.empty()) {
string ros_package_path1 = ros::package::getPath("speech_command");
std::string wav_path1 = ros_package_path1 + document;
std::string command1 = "play " + wav_path1;
system(command1.c_str());
} else {
cout << "未找到问题对应的音频文件: " << question_str << endl;
}
问题三:节点启动时崩溃(音频设备占用与内存错误)
症状
roslaunch
启动时节点异常退出,关键错误:
- 无法打开音频设备: 2,0 (Device or resource busy)
- free(): double free detected in tcache 2
占用程序所需音频设备(实际为hw:XFMDPV0018
,日志打印存在误导)。
内存错误
AIUITester.cpp
中使用audioRecorder->~AudioRecorder();
非标准方式调用析构函数,导致内存重复释放。
解决方案
设备占用
- 在机器人终端使用
fuser -v /dev/snd/*
命令查找并kill占用音频设备的进程。 - (可选)修正
AIUITester.cpp
中的printf
语句,打印正确设备名pcm_name
。
内存错误
修改AIUITester.cpp
的destory
函数,使用标准delete
关键字释放对象。
代码修正
// 在 AIUITester::destory() 中
// 修改前: audioRecorder->~AudioRecorder();
// 修改后: delete audioRecorder;
问题四:RViz启动失败(图形驱动与主机名解析)
阶段A:RViz因图形驱动不兼容崩溃
症状
启动RViz时出现libGL error: unable to load driver: rockchip_dri.so
错误并伴随Segmentation fault
段错误。
根本原因
Ucar机器人嵌入式环境(Rockchip主板)缺少或无法加载RViz依赖的3D硬件加速驱动;启动文件ucar_gmapping.launch
错误包含本地启动RViz的节点。
解决方案
- 修改启动文件:编辑
~/ucar_ws/src/ucar_map/launch/ucar_gmapping.launch
,注释掉RViz节点。 - 采用"PC端远程可视化"方案(ROS开发标准工作流程)。
阶段B:RViz在PC端启动但无法显示数据
症状
PC端RViz启动成功但不显示机器人数据,报错:
Couldn't find an AF_INET address for [superbrain]: 域名解析暂时失败
根本原因
PC操作系统不识别机器人主机名superbrain
,无法解析为IP地址,导致节点通信失败。
解决方案
方法1(推荐):设置ROS_IP(机器人端)
# 启动roscore终端
export ROS_IP=<机器人IP地址>
roscore
# 启动主程序终端
export ROS_IP=<机器人IP地址>
roslaunch ucar_map ucar_gmapping.launch
方法2(备选):手动映射主机名到IP
- Linux/Mac:编辑
/etc/hosts
- Windows:以管理员身份编辑
C:\Windows\System32\drivers\etc\hosts
添加:192.168.141.32 superbrain
(IP替换为机器人实际IP)
问题五:ROS网络核心roscore启动失败
症状
机器人运行roscore
时报错:
RLException: Unable to contact my own server at [...]
根本原因
机器人环境变量ROS_IP
设置为过时或错误IP(可能固化在~/.bashrc
中),导致roscore
无法自通信。
解决方案
- 临时取消设置:
unset ROS_IP
和unset ROS_HOSTNAME
。 - 检查并编辑
~/.bashrc
:nano ~/.bashrc
,注释掉export ROS_IP=...
行。 - 刷新配置:
source ~/.bashrc
。
总结与最佳实践
核心开发原则
-
计算与可视化分离
嵌入式项目中,计算密集型无界面节点(驱动、算法)运行在机器人上,图形工具(RViz、rqt_plot)运行在PC端。 -
稳健的网络配置
多机通信优先使用IP地址配置(通过ROS_IP
和ROS_MASTER_URI
),避免主机名解析失败导致通信中断。 -
规范的编码与内存管理
遵循C++标准内存管理(new/delete
配对),避免非规范操作(如手动调用析构函数)。 -
系统性调试思路
从日志入手,逐层分析(应用层代码逻辑→环境层驱动/网络),定位问题时采用"排除法"缩小范围。
额外建议
- 定期检查系统资源占用(如音频设备、端口),使用
fuser
、lsof
等工具排查冲突。 - 维护清晰的环境变量配置,避免在
.bashrc
中固化静态IP,改为动态设置。 - 开发阶段保留详细调试日志,便于复现和追溯问题。