EPRobot 学习进展记录|最近阶段
一、当前整体目标发生了什么变化
这一阶段一开始,我们主要是在解决:
Ubuntu 能不能通过 ROS 控制小车 → RViz 能不能显示雷达和地图 → 能不能自己 SLAM 扫图。
现在已经进一步推进到了:
直接使用队友扫好的地图 → 加载静态地图 → AMCL 定位 → move_base + TEB 自主导航。
也就是说,已经从"把车跑起来"进入了真正的导航阶段。
二、ROS 多机通信重新跑通
目前小车 EPRobot 的 IP:
172.20.10.3
Ubuntu 与小车已经能互相通信。
Ubuntu 中 ROS 配置确认过:
echo $ROS_MASTER_URI
返回:
http://EPRobot2:11311
Ubuntu:
echo $ROS_HOSTNAME
返回:
ubuntu
EPRobot:
echo $ROS_MASTER_URI
也是:
http://EPRobot:11311
并且 EPRobot 自己的 ROS 主机名配置正常。
本阶段再次确认的重要知识
ROS 多机通信不仅要求:
Ubuntu → 能找到 EPRobot
还必须:
EPRobot → 能找到 ubuntu
之前出现过:
ping ubuntu
竟然解析成:
10.189.140.66
导致 EPRobot 无法访问 Ubuntu。
原因是 /etc/hosts 里 ubuntu 对应的 IP 已经过期。
所以再次明确:
每次换手机热点 / IP 改变,都要检查
/etc/hosts。
三、/cmd_vel 控制问题
之前我们一直测试:
rostopic pub -r 5 /cmd_vel geometry_msgs/Twist ...
一开始出现过一个很奇怪的问题:
Ubuntu 发
/cmd_vel,小车有时不动;在 EPRobot 终端发,同样指令却能动。
后来逐步确认:
rostopic info /cmd_vel
能看到:
Subscribers:
* /base_control
说明底盘控制节点确实订阅 /cmd_vel。
然后检查:
rosnode info /base_control
确认:
Subscriptions:
/cmd_vel
程序源码中也确认了:
self.cmd_vel_topic = rospy.get_param('~cmd_vel_topic','/cmd_vel')
self.sub = rospy.Subscriber(self.cmd_vel_topic,Twist,self.cmdCB,...)
也就是说:
/cmd_vel就是正确的控制话题。
四、为什么 Ctrl+C 后小车还不立即停
使用:
rostopic pub -r 5 /cmd_vel ...
代表:
以 5Hz 持续不断发送速度指令。
所以终端会一直占着,这不是"卡住"。
停止发布:
Ctrl+C
但为了确保小车马上收到"速度=0"的指令,我们后来固定采用:
rostopic pub -1 /cmd_vel geometry_msgs/Twist \
'{linear: {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}'
最终确认:
前进命令 → Ctrl+C → 再发一次 0 速度
可以全部在 Ubuntu 同一个终端完成。
五、安装了键盘遥控节点 teleop_twist_keyboard
因为手工敲 /cmd_vel 太麻烦,而且不好控制扫图,所以我们开始安装:
teleop_twist_keyboard
其中teleoperation就是远程操控的意思
六、解决 Ubuntu apt 被占用的问题
安装时执行:
sudo apt install ros-melodic-teleop-twist-keyboard
出现:
无法获得锁 /var/lib/dpkg/lock-frontend
检查:
sudo lsof /var/lib/dpkg/lock-frontend
发现是:
unattended-upgrade
PID 2281
一直占着锁,而且跑了几个小时。
普通:
sudo kill 2281
都没停掉。
最后使用:
sudo kill -9 2281
才结束。
之后成功安装:
sudo apt install ros-melodic-teleop-twist-keyboard
再验证:
rospack find teleop_twist_keyboard
成功返回:
/opt/ros/melodic/share/teleop_twist_keyboard
结论
键盘遥控包安装成功。
七、键盘控制小车已经实现
补充一个ros的语法:rosrun 包名 节点可执行文件
比如
启动:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py
成功出现:
Reading from the keyboard and Publishing to Twist!
按键:
u i o
j k l
m , .
主要记:
i 前进
, 后退
k 停止
u 前进+左转
o 前进+右转
m 后退+左转
. 后退+右转
调速度:
q/z 整体速度 +10% / -10%
w/x 只调线速度 +10% / -10%
e/c 只调转向速度 +10% / -10%
第一次实际扫图时,把速度从:
speed 0.5
turn 1.0
一直降到了大约(按键盘里的z)
speed ≈ 0.15
turn ≈ 0.31
八、进一步理解了阿克曼底盘
EPRobot 是:
后轮驱动 + 前轮转向的阿克曼底盘。
不是那种可以左右轮反向、原地旋转的小车。
所以更像汽车:
后轮 → 推动车前后运动
前轮 → 改变转向角
因此实际控制最适合:
i 直走
u/o 边走边转
k 停
而不是频繁用 j/l 原地转。
手册也明确说明 EPRobot 是后轮驱动、前轮转向的阿克曼结构。EPRobotV2智能小车使用手册-202505(1)
九、RViz 显示配置搞明白了
RViz 里学习了:
Fixed Frame = map
添加:
Map → /map
LaserScan → /scan
并且知道:
Add → By topic
对于已经存在的话题最方便。
RViz 配置也保存过。
地图显示含义
白色 已判断为可通行区域
黑色 障碍物/墙
灰绿色 未知、尚未扫描区域
十、第一次真正跑 GMapping 建图
正式启动:
roslaunch robot_navigation robot_slam_laser.launch slam_methods:=gmapping
确认:
rosnode list | grep gmapping
出现:
/gmapping
再检查:
rostopic info /map
看到:
Publishers:
/gmapping
所以确认:
/scan + /odom → gmapping → /map
这一整条建图链路已经跑起来。
十一、解决了一个非常关键的 TF 问题
当时虽然:
/gmapping
/map
/odom
/scan
都有了,但 RViz 仍然:
No tf data
执行:
rosrun tf tf_echo map base_link
报:
Could not find a connection between 'map' and 'base_link'
TF has two or more unconnected trees
检查发现 TF 是断开的:
map
↓
odom
以及
base_footprint
↓
base_link
↓
base_laser_link
缺:
odom → base_footprint
十二、最终定位到参数 is_pub_odom_tf
执行:
rosparam get /base_control/is_pub_odom_tf
返回:
false
但是:
rostopic echo -n 1 /odom
已经有:
frame_id: "odom"
child_frame_id: "base_footprint"
这说明:
里程计消息
/odom有,但没有发布对应 TF。
搜索:
grep -R -n "is_pub_odom_tf" \
~/robot_ws/src/eprobot_start \
~/robot_ws/src/robot_navigation
发现:
EPRobot_start.launch → true
robot_lidar.launch.bak_nav → true
robot_lidar.launch → false
所以修改:
~/robot_ws/src/robot_navigation/launch/robot_lidar.launch
把:
<param name="is_pub_odom_tf" type="string" value="false"/>
改成true:
<param name="is_pub_odom_tf" type="string" value="true"/>
重新启动 SLAM 后:
rosrun tf tf_echo map base_link
终于开始连续输出:
Translation: ...
Rotation: ...
这一步非常重要
正确 TF 树变成:
map
↓
odom
↓
base_footprint
↓
base_link
↓
base_laser_link
这也是这一阶段非常关键的一个故障排查成果。
十三、自己实际体验了一次完整扫图
使用:
GMapping + teleop_twist_keyboard + RViz
真的把场地扫出来过。
但第一版地图出现:
射线状发散
墙体重影
边界撕裂
地图发生扭曲

后来分析主要与:
转弯太快
频繁左右修正
阿克曼底盘运动特点
里程计累计误差
激光匹配不稳定
有关。
后来重新清空:
rosnode kill /gmapping
确认:
rostopic info /map
一度变成:
Publishers: None
再重新启动 gmapping。
RViz 里的旧 Map 也:
Remove
再重新:
Add → /map → Map
从而真正开始了一张新地图。
十四、最终决定:不继续自己扫,使用队友地图
虽然已经完整体验过 GMapping 建图,但因为队友的地图质量更好,所以决定:
比赛导航直接使用队友已经扫好的地图。
队友地图位置:
~/robot_ws/src/robot_navigation/maps
文件:
map.pgm
map.yaml
执行:
cd ~/robot_ws/src/robot_navigation/maps
ls -lh map.pgm map.yaml
确认地图存在。
单独测试过:
source ~/robot_ws/devel/setup.bash
rosrun map_server map_server
~/robot_ws/src/robot_navigation/maps/map.yaml
成功输出:
Loading map from image ".../map.pgm"
Read a 384 X 384 map @ 0.050 m/cell
说明:
map.yaml + map.pgm完整有效。
十六、开始进入正式"二维自主导航"
官方流程:
roslaunch robot_navigation robot_navigation.launch
用于启动导航。
EPRobot 手册明确说明,地图构建完成后就可以进入二维地图自主导航;这套小车使用 TEB 作为适配阿克曼底盘的导航/局部规划算法。EPRobotV2智能小车使用手册-202505(1)(2)
这次启动成功后,终端出现:
Received a 384 X 384 map @ 0.050 m/pix
还有:
base control start...
is_pub_odom_tf : true
Serial Open Succeed
说明:
地图 ✅
底盘 ✅
odom TF ✅
串口 ✅
十七、导航代价地图也已经起来
启动过程中看到:
global_costmap: Using plugin "static_layer"
global_costmap: Using plugin "obstacle_layer"
global_costmap: Using plugin "inflation_layer"
以及:
local_costmap ...
目前可以简单理解:
static_layer
= 队友地图里的固定墙和障碍物
obstacle_layer
= 激光雷达实时看到的新障碍
inflation_layer
= 在障碍物周围留安全距离
所以导航时不是只看 map.pgm,而是:
已有地图
+
实时雷达障碍
+
安全膨胀区域
一起决定哪里能走。
十八、确认 AMCL 和 move_base 已经工作
Ubuntu 执行:
rostopic info /map
现在看到:
Publishers:
* /map_server
说明当前已经不是 GMapping 在实时建图,而是:
map_server 正在发布队友的静态地图。
并且:
Subscribers:
* /amcl
* /move_base
这两个非常重要。
可以理解为:
map_server
↓
队友静态地图
↓
AMCL → 我现在在哪里?
move_base → 我要怎么走到目标?
十九、RViz 现在用于"导航",不是"建图"
Ubuntu 本地没有:
navigation_rviz.launch
所以执行:
roslaunch robot_navigation navigation_rviz.launch
会报:
is neither a launch file ...
原因是 Ubuntu 本地没有这个 robot_navigation 包/launch 文件。
但不影响使用。
直接:
rviz
即可。
然后:
Fixed Frame = map
Add
→ By topic
→ /map
→ Map
就能看到队友的地图。
二十、刚学到的两个导航按钮
现在已经进行到:
2D Pose Estimate
意思:
告诉 AMCL:"现实中的小车现在在地图哪里、车头朝哪边。"
操作:
点击 2D Pose Estimate
→ 在地图中真实小车对应位置按下鼠标
→ 拖出箭头
其中:
箭头起点 = 小车位置
箭头方向 = 车头方向
可以记:
2D Pose Estimate = 我现在在哪?
2D Nav Goal
之后才用。
意思:
告诉导航系统:我要去哪。
同样:
目标点位置 + 目标车头方向
然后:
move_base + TEB
会自己规划路线并控制小车过去。
记:
2D Nav Goal = 我要去哪?
二十一、到目前为止整套系统可以这样理解
现在最重要的一张逻辑图:
ROS Master
│
│
┌─────────────┴─────────────┐
│ │
EPRobot Ubuntu
│ │
│ RViz
│ │
│ 显示地图/定位/路径
│
├── map_server
│ │
│ └── 队友 map.yaml + map.pgm
│
├── 激光雷达 /scan
│
├── 底盘 /odom
│
├── TF
│
├── AMCL
│ └── 判断"小车在哪"
│
└── move_base + TEB
└── 判断"怎么走到目标"
二十二、目前进度停在哪里
现在已经完成:
✅ Ubuntu ↔ EPRobot ROS 多机通信
✅ Bitvise SSH
✅ roscore
✅ 底盘 /cmd_vel
✅ 键盘遥控 teleop_twist_keyboard
✅ RViz
✅ LaserScan
✅ GMapping
✅ /map
✅ /odom
✅ TF 树修复
✅ 自己体验 SLAM 扫图
✅ 队友 map.pgm + map.yaml 加载
✅ map_server
✅ AMCL
✅ move_base
✅ global/local costmap
✅ TEB 导航框架启动
✅ RViz 显示队友地图