本次最重要的成果:成功恢复了之前缺失的激光雷达TF坐标变换,使AMCL能够输出位姿,RViz重新正常显示地图和激光扫描。
但完整比赛尚未跑通,小车在前往识别板一时向右偏移并碰撞显示屏,随后人工停止。
一、这次一共打开了哪些终端?
小车端:4个 PowerShell SSH 终端
每新开一个窗口,首先连接小车:
ssh EPRobot@172.20.10.2
终端1:ROS Master
roscore
作用:启动 ROS 主节点,负责系统中节点之间的注册和通信。
终端2:底盘与传感器
source ~/robot_ws/devel/setup.bash
roslaunch eprobot_start EPRobot_start.launch
作用:启动 EPRobot 基础驱动和传感器相关功能。
终端3:定位与导航
source ~/robot_ws/devel/setup.bash
roslaunch robot_navigation robot_race_init.launch
作用:启动地图、AMCL、move_base、TEB局部规划器及相关导航功能。
终端4:调试与比赛程序
本次先用它排查 TF、激光雷达和 AMCL,最后启动比赛主程序。
source ~/robot_ws/devel/setup.bash
cd ~/robot_ws/src/pharmacy_pkg/scripts
python smart_pharmacy2.py
Ubuntu端:1个终端
Ubuntu/car中启动 RViz,不单独启动 roscore:
source /opt/ros/melodic/setup.bash
unset ROS_HOSTNAME
export ROS_IP=172.20.10.5
export ROS_MASTER_URI=http://172.20.10.2:11311
rviz
注意,本次 Ubuntu 虚拟机中没有找到:
~/robot_ws/devel/setup.bash
因此直接使用 ROS Melodic 安装目录的环境配置,并通过 rviz 启动,不再调用不存在的 navigation_rviz.launch。
二、Ubuntu虚拟机卡死、黑屏问题
1. 遇到的问题
最开始 Ubuntu(car) 虚拟机卡顿严重,甚至出现黑屏。
查看 VMware 配置发现:
-
内存:4GB
-
处理器核心:1
-
虚拟机处于挂起状态
另外,虚拟机画面曾出现:
A stop job is running for Unattended Upgrades Shutdown
这提示 Ubuntu 在某次关机过程中等待自动更新服务结束。
因此,卡顿不一定完全由内存不足造成。
2. 本次调整
查看 Windows 任务管理器发现电脑有16GB运行内存。
最后把 Ubuntu(car) 改为:
| 配置 | 调整前 | 调整后 |
|---|---|---|
| RAM | 4GB | 6GB(6144MB) |
| CPU核心 | 1核 | 4核 |
| 硬盘 | 20GB | 不变 |
| 网络 | VMnet0 | 不变 |
重新启动后,Ubuntu成功进入桌面,RViz也能够正常打开。
结论:本次通过调整资源并重新启动恢复了Ubuntu,但不能证明原先黑屏完全由内存不足导致。
三、RViz地图配置:具体 Add 了什么?
这次没有使用现成的 RViz launch 文件,而是直接运行:
rviz
打开后,在 RViz 的左侧 Displays 面板设置:
Global Options → Fixed Frame → map
然后配置以下显示项。
| RViz显示项 | Topic或设置 | 作用 |
|---|---|---|
| Grid | 默认 | 显示坐标网格 |
| Map | /map |
显示比赛场地地图 |
LaserScan((topic里) |
/scan |
显示激光雷达扫描 |
| PoseArray(display type里) | /particlecloud |
显示AMCL粒子分布 |
| TF(display type里) | 默认 | 显示机器人各坐标系 |
| Path(display type里) | 选择实际导航路径话题 | 显示规划路径 |
RViz颜色报错

最初出现:
Global Status: Error
Fixed Frame [map] does not exist
以及:
LaserScan Status: Error
For frame [base_laser_link]:
Fixed Frame [map] does not exist
这说明当时无法完成激光雷达到地图坐标系的转换。
后来通过修复 TF,最终截图显示:
-
Global Status:OK
-
Fixed Frame:OK
-
LaserScan:OK
-
地图正常显示
-
雷达轮廓基本与地图边框吻合
这是本次最明显的修复成果。
四、!!!最核心的故障:TF坐标变换缺失
1. 一开始查出了什么?
在小车第四个终端输入:
rosrun tf tf_echo map base_footprint
最初返回:
"map" passed to lookupTransform
argument target_frame does not exist.
检查激光雷达坐标:
rosrun tf tf_echo base_footprint base_laser_link
也报:
"base_laser_link" passed to lookupTransform
argument source_frame does not exist.
这时 ROS 实际只识别到:
odom
└── base_footprint
也就是说,ROS能够获得小车的里程计关系,但不知道激光雷达相对于小车主体的位置。
这会妨碍 AMCL 使用激光扫描进行定位。
2. 我们怎样一步步定位原因?
先检查 AMCL:
rosnode list | grep amcl
rosservice list | grep static_map
rostopic list | grep -E '^/map$|^/amcl_pose$|^/particlecloud$'
发现相关节点、服务和话题均存在。
再查地图:
rostopic echo -n 1 /map/info
得到:
resolution: 0.05
width: 384
height: 384
origin:
x: -10.0
y: -10.0
地图存在且有数据。
然后查激光:
rostopic hz /scan_filtered
得到约:
average rate: 10.0
再查消息坐标系:
rostopic echo -n 1 /scan_filtered/header
得到:
frame_id: "base_laser_link"
说明激光数据正常发布,但相应TF坐标系缺失。
接着查询:
rosnode info /amcl
rosparam get /amcl/tf_broadcast
确认 AMCL 订阅 /map、/scan_filtered,且 tf_broadcast 为 true。
因此排查重点转向 TF 发布配置。
3. 找到了哪个启动文件?
查看:
roscd eprobot_start
find . -name "*.launch"
以及:
roscd robot_navigation
find . -name "*.launch"
再搜索 TF 相关配置。
最终在已有启动文件中找到:
robot_lidar.launch:
<node pkg="tf"
type="static_transform_publisher"
name="base_to_link"
args="0.08 0 0 0 0 0 base_footprint base_link 20" />
还有 robot_race_init.launch 中的雷达变换:
<node pkg="tf"
type="static_transform_publisher"
name="base_to_laser"
args="0.05 0 0.11 0 0 0 base_link base_laser_link 100"/>
同时发现若干其他静态变换配置被 XML 注释包围,没有生效。
查询正在运行的节点,未找到预期的 base_to_link、base_to_laser、base_to_gyro。
所以最直接的问题是:本次运行环境没有提供这两段必需的静态坐标变换。 至于原启动文件为什么未成功提供它们,还需要以后检查启动条件或节点退出日志。
4. 最终怎么修好的?
我们没有修改启动文件,而是临时手动运行了两条命令。
恢复 base_footprint → base_link:
rosrun tf static_transform_publisher 0.08 0 0 0 0 0 base_footprint base_link 20 > /tmp/tf_link.log 2>&1 &
恢复 base_link → base_laser_link:
rosrun tf static_transform_publisher 0.05 0 0.11 0 0 0 base_link base_laser_link 100 > /tmp/tf_laser.log 2>&1 &
其中:
-
0.08表示小车主体沿X方向相对于底盘参考点偏移0.08m。 -
0.05表示雷达沿X方向相对于主体偏移0.05m。 -
0.11表示雷达沿Z方向相对于主体偏移0.11m。 -
&表示在后台运行。
再次执行:
rosrun tf tf_echo base_footprint base_laser_link
得到:
Translation: [0.130, 0.000, 0.110]
Rotation: Quaternion [0.000, 0.000, 0.000, 1.000]
符合:
\ 0.08+0.05=0.13\\text{ m} \\
这证明两段静态TF已经成功连通。
但是注意,这只是临时恢复。下次重新启动小车或相关进程后,仍可能需要重新发布;长期应修复原有 launch 文件,避免重复TF发布。
五、AMCL定位恢复过程
恢复激光 TF 后,回到 Ubuntu 的 RViz。
使用:
2D Pose Estimate
在地图上的实际 START 起点位置设置小车初始位姿,箭头朝向与车头一致。
随后再次检查:
rostopic echo -n 1 /amcl_pose
这次终于有了定位数据:
position:
x: 1.3530485
y: 1.3353472
orientation:
z: 0.5861939
w: 0.8101707
再运行:
rosrun tf tf_echo map base_footprint
最初短暂出现时间外推警告:
Lookup would require extrapolation into the past.
但随后连续输出:
Translation: [1.353, 1.335, 0.000]
Rotation in RPY (degree):
[0.000, -0.000, 71.775]
说明全局定位变换链已经建立。
最终 TF 结构:
map
└── odom
└── base_footprint
└── base_link
└── base_laser_link
当前估计位姿与原始起点对比
| 数据 | 原程序起点 | 本次AMCL |
|---|---|---|
| X | 1.323 m | 1.353 m |
| Y | 1.268 m | 1.335 m |
| 朝向 | 约67.9° | 约71.8° |
位置相差约7.4cm、角度相差约3.9°。
所以从数值上看,AMCL估计位置接近之前保存的起点。
但是这并不意味着定位足够精确,因为当时位姿协方差仍然偏大,而且后续实际导航发生了碰撞。
六、正式启动比赛程序
完成 TF 和 RViz 检查后,进入小车第四个终端。
执行:
source ~/robot_ws/devel/setup.bash
cd ~/robot_ws/src/pharmacy_pkg/scripts
先查看:
ls -lh smart_pharmacy2.py pharmacy_extensions.py
本次看到:
pharmacy_extensions.py 29K
smart_pharmacy2.py 31K
再确认没有旧的比赛进程:
pgrep -af 'smart_pharmacy2.py'
没有输出。
最后执行:
python smart_pharmacy2.py
本次比赛主程序的预期流程
-
从START起点出发,导航到识别板一
-
读取四个候选二维码,过滤干扰任务
-
按照任务依次前往A/B/C取样
-
到达识别板二并进行OCR识别
-
前往对应的1~4号化验窗口
-
完成配送核验,返回起点
不过本次实际只运行了第一个阶段。
新版程序与旧版的区别
最开始给我的旧版使用里程计控制直行约79cm。
本次最新版已经更改为:
planner_client = DynamicClient('/move_base/TebLocalPlannerROS', timeout=5.0)planner_client.update_configuration({'xy_goal_tolerance': 0.03})
随后通过 move_base 导航到识别板一。
smart_pharmacy2.py
目标坐标为:
Board1 target:
x = 1.7549
y = 1.9838
position tolerance = 0.03m
因此当前依靠 AMCL、全局规划、TEB局部规划和底盘控制共同完成第一段运动,而不是旧版的固定速度直行。
七、本次运行失败:小车向右跑偏并撞到显示屏
1. 现场实际现象
启动比赛主程序后,小车没有按预期安全到达识别板一,而是向右偏移并碰撞显示屏。
因此人工按下 Ctrl+C 停止程序。
终端随后显示:
Goal failed with state: 2
以及:
Competition stopped; manual inspection required:
Navigation failed: board1
其中 state: 2 对应 ROS actionlib 的 PREEMPTED 状态,表示目标被取消或抢占。
因为它出现在人工中断之后,所以不能将这条日志直接当作碰撞原因。
另外还出现:
Round exception: service call failed
这发生在中断后的故障处理阶段,也不能据此认定它导致了撞墙。
2. 目前怀疑的原因
| 怀疑方向 | 具体问题 |
|---|---|
| AMCL | 定位不稳定、起点朝向估计误差 |
| TEB | 局部路径规划或转向参数不合适 |
| local_costmap | 未正确检测显示屏障碍物 |
| 里程计/IMU | 轮速、姿态或传感器融合误差 |
| TF | 雷达TF虽然连通,但真实安装参数尚未完全核实 |
| 底盘 | 左右轮实际速度不同,控制指令执行偏差 |
目前还不能证明是 AMCL 粒子数量造成的,因此不应直接通过增加粒子数量解决撞墙。
下一阶段的首要目标应是安全验证定位、避障与转向控制,不能在未排除原因前再次完整自动运行。
九、裁判软件与 TCP 连接问题
本次比赛主程序还一直报:
Judge TCP reconnect: timed out
后来你打开 Smart 裁判软件,发现:
-
TCP裁判服务器监听端口:8888。
-
界面列出了本机网络地址
192.168.55.1、192.168.61.1。 -
小车当前在
172.20.10.2。
最新版 pharmacy_extensions.py 的裁判发送器会读取 ROS 参数中的裁判服务器IP和端口,并建立 TCP 连接。
pharmacy_extensions.py
因此,下次比赛建议先启动裁判软件并确认正确的网络地址和端口,再启动小车比赛主程序。
但是不能仅凭裁判软件已打开就认为连接成功,还需要检查小车能否访问裁判软件实际监听的网络接口。
这条TCP超时与本次撞墙属于两个不同问题。
十、本次调试结果总表
| 项目 | 结果 |
|---|---|
| 小车SSH连接 | 已成功 |
| ROS Master | 已启动 |
| 底盘与传感器 | 已启动 |
| Ubuntu黑屏 | 已恢复 |
| 虚拟机资源 | 调整为6GB、4核 |
| RViz地图 | 正常显示 |
| 激光雷达数据 | 约10Hz |
| 激光TF缺失 | 已临时修复 |
| AMCL位姿输出 | 已恢复 |
map → odom |
已恢复 |
| 裁判TCP通信 | 尚未验证成功 |
| 识别板一导航 | 发生碰撞,未完成 |
| 二维码识别 | 本次未到达该阶段 |
| A/B/C取样 | 未开始 |
| 化验区配送 | 未开始 |
| 返回起点 | 未执行 |
最后总结
这次最大的成果不是跑通比赛,而是成功恢复了ROS的TF与AMCL定位链路,并把问题缩小到了真正的导航和底盘控制层。
我们已经解决了"雷达有数据但ROS不知道雷达在哪里"的问题;现在要解决的是"ROS认为小车应该怎么走,为什么实体小车却向右撞到了显示屏"。
下一阶段应以最新版 robot_navigation 配置为基础,检查 AMCL定位精度、TEB局部规划、costmap避障,以及底盘对速度指令的执行情况。