TurtleBot3 SLAM建图、自主导航与避障完整实战教程含源码 前言一、环境准备1.1 系统要求1.2 安装ROS依赖包1.3 安装TurtleBot3专用包1.4 下载TurtleBot3仿真包1.5 配置工作空间自动加载二、Gazebo仿真基础2.1 启动TurtleBot3 World2.2 启动TurtleBot3 House2.3 键盘控制机器人三、SLAM建图3.1 建图流程3.2 建图技巧3.3 保存地图四、自主导航4.1 启动导航4.2 设置初始位置4.3 精确定位可省略4.4 设置导航目标五、任务一绕桩巡航TurtleBot3 World5.1 任务目标5.2 实现思路5.3 扫描地图5.4 创建脚本5.5 代码核心解析5.6 运行任务一六、任务二自主避障TurtleBot3 House6.1 任务目标6.2 实现思路6.3 创建脚本6.4 代码核心解析6.5 运行任务二七、常见问题排查7.1 报错Failed to create the dwa_local_planner7.2 报错Aborting on goal because it was sent with an invalid quaternion7.3 dpkg被中断错误7.4 虚拟机网络故障详细排查重点7.4.1 先诊断网络状态7.4.2 修复方法一重启网络管理服务7.4.3 修复方法二手动启用网卡7.4.4 修复方法三检查VMware网络适配器设置7.4.5 修复方法四重启VMware服务在Windows宿主机操作7.4.6 修复方法五更换软件源7.5 避障时机器人撞墙不转7.6 导航目标点瞬间失败7.7 RViz 中地图区域空白九、总结前言本教程基于Ubuntu 20.04 ROS Noetic环境使用TurtleBot3 Gazebo仿真平台从零开始完成 SLAM 建图、自主导航、绕桩巡航、自主避障四个完整任务并附上所有源代码。适合 ROS 初学者、机器人课程学生、自学小白导航入门。完整代码已开源到 GitHubhttps://github.com/EnoXie422/turtlebot3-slam-navigation若本文对你有帮助欢迎点个 Star⭐ 支持一下 全文所有命令均经过实际测试可直接复制使用。每个关键步骤附有截图说明。一、环境准备1.1 系统要求项目版本虚拟机VMware操作系统Ubuntu 20.04 LTSROS版本ROS Noetic仿真器Gazebo 11PythonPython 31.2 安装ROS依赖包打开终端Ctrl Alt T输入以下命令sudoapt-getinstallros-noetic-joy ros-noetic-teleop-twist-joy\ros-noetic-teleop-twist-keyboard ros-noetic-laser-proc\ros-noetic-rgbd-launch ros-noetic-rosserial-arduino\ros-noetic-rosserial-python ros-noetic-rosserial-client\ros-noetic-rosserial-msgs ros-noetic-amcl ros-noetic-map-server\ros-noetic-move-base ros-noetic-urdf ros-noetic-xacro\ros-noetic-compressed-image-transport ros-noetic-rqt* ros-noetic-rviz\ros-noetic-gmapping ros-noetic-navigation ros-noetic-interactive-markers1.3 安装TurtleBot3专用包sudoaptinstallros-noetic-dynamixel-sdksudoaptinstallros-noetic-turtlebot3-msgssudoaptinstallros-noetic-turtlebot3sudoaptinstallros-noetic-dwa-local-planner⚠️重要dwa-local-planner必须安装否则导航时会报错Failed to create the dwa_local_planner/DWAPlannerROS planner1.4 下载TurtleBot3仿真包cd~/catkin_ws/src/gitclone-bnoetic https://github.com/ROBOTIS-GIT/turtlebot3_simulations.gitcd~/catkin_wscatkin_make你将看到这样的内容编译完成后会显示[100%]无红色报错即为成功1.5 配置工作空间自动加载echosource ~/catkin_ws/devel/setup.bash~/.bashrcsource~/.bashrc二、Gazebo仿真基础TurtleBot3提供三种仿真世界世界名称推荐机器人用途Empty Worldburger测试基本运动TurtleBot3 WorldburgerSLAM建图、绕桩任务TurtleBot3 Housewaffle_piSLAM建图、避障任务2.1 启动TurtleBot3 WorldexportTURTLEBOT3_MODELburger roslaunch turtlebot3_gazebo turtlebot3_world.launch应该能看到一个六边形场地中间有9个绿色圆柱桩呈3×3排列机器人在初始位置2.2 启动TurtleBot3 HouseexportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_gazebo turtlebot3_house.launch⏳ 第一次启动House会下载模型可能需要几分钟应该能看到一个完整的房屋场景包含客厅、卧室、厨房等多个房间2.3 键盘控制机器人新开一个终端exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch控制按键按键功能W前进S后退A左转D右转X或SPACE停止终端会显示按键说明、当前速度等信息三、SLAM建图SLAMSimultaneous Localization And Mapping即同时定位与建图让机器人边走边构建地图。3.1 建图流程需要同时打开4个终端终端1启动Gazebo世界exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_gazebo turtlebot3_house.launch终端2启动Gmapping SLAM节点exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:gmapping启动后会弹出 RViz 窗口能实时看到地图被绘制出来。刚启动SLAM时的RViz界面就是这样此时地图基本是空白的只能看到机器人周围一小圈被扫描的区域终端3键盘控制机器人exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch3.2 建图技巧为了获得高质量地图建议遵循以下原则速度要慢移动速度越慢激光雷达扫描越完整先转后走避免边转弯边前进会导致地图扭曲✅ 正确原地旋转扫描 → 直线前进 → 到达新位置后再旋转❌ 错误螺旋式前进沿墙行走先沿墙绕一圈再进入每个房间内部观察RViz灰色区域 未扫描需要前往黑白分明 扫描完成地图跳动 速度过快停下重新校准注地图的形状可能在扫描时因操作或其他的原因不是十分方正在此实验中只要地图形状没有特别明显的错误都可以完成3.3 保存地图地图绘制完成后新开终端4保存rosrun map_server map_saver-f~/map_house注House地图保存为map_houseWorld地图保存为map_world方便区分保存成功后会在用户目录生成两个文件map_house.pgm地图图像map_house.yaml地图配置文件四、自主导航导航功能基于已建好的地图使用 ROS 的move_base框架自动规划路径。4.1 启动导航终端1启动GazeboexportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_gazebo turtlebot3_house.launch终端2启动导航节点exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:$HOME/map_house.yaml能看到完整地图机器人位置可能不准确地图上还没有定位粒子不用担心现在位置很乱现在机器人在地图里的位置和我们建模的位置不在一起我们接下来就要改变初始位置4.2 设置初始位置RViz 启动后机器人不知道自己在哪需要手动告诉它点击RViz顶部工具栏的2D Pose Estimate按钮在地图上机器人实际所在的位置点击并拖动拖动方向 机器人面朝的方向松开鼠标后地图上会出现一群绿色小箭头粒子云同时也可以看到我们建模所生成的边界抖动的绿色点形成的边线和地图位置相重合4.3 精确定位可省略为了让 AMCL 算法收敛需要让机器人稍微移动一下exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch用W A S D让机器人前后晃动几次绿色箭头会聚拢说明定位精确了。⚠️ 定位完成后必须按 CtrlC 关闭键盘控制终端否则会与导航指令冲突4.4 设置导航目标点击RViz顶部的2D Nav Goal按钮在地图上目标位置点击并拖动箭头箭头根部 目标坐标 (x, y)箭头方向 到达目标后的朝向 θ松开鼠标机器人会自动规划路径并行驶RViz中机器人和目标点之间出现一条彩色路径线全局规划机器人开始沿路径移动最后会看到机器人成功到达目标位置姿态也与目标箭头一致五、任务一绕桩巡航TurtleBot3 World5.1 任务目标让机器人在 TurtleBot3 World 中自主沿着九个圆柱桩的外围走一圈。* * * ← 九个圆柱桩 * * * * * * 机器人需绕外围一圈5.2 实现思路利用move_base导航框架依次发送8个目标点给机器人让它形成一个环绕外围的路径(-1.5, 1.5) → (0, 2.0) → (1.5, 1.5) ↑ ↓ (-2.0, 0) (2.0, 0) ↑ ↓ (-1.5,-1.5) ← (0,-2.0) ← (1.5,-1.5)5.3 扫描地图因为绕桩巡航需要在World里跑需要World的地图按照前文三、SLAM建图的流程仿照之前TurtleBot3 House地图建模流程对TurtleBot3 World重新建图终端1启动World场景exportTURTLEBOT3_MODELburger roslaunch turtlebot3_gazebo turtlebot3_world.launch终端2 — 启动SLAMexportTURTLEBOT3_MODELburger roslaunch turtlebot3_slam turtlebot3_slam.launch slam_methods:gmapping终端3 — 键盘控制exportTURTLEBOT3_MODELburger roslaunch turtlebot3_teleop turtlebot3_teleop_key.launch终端4 — 保存World地图rosrun map_server map_saver-f~/map_world注意这次保存名字叫 map_world和之前House的地图分开5.4 创建脚本mkdir-p~/scripts gedit ~/scripts/task3_circle.py在打开的编辑器中粘贴以下代码#!/usr/bin/env python3importrospyimportactionlibfrommove_base_msgs.msgimportMoveBaseAction,MoveBaseGoalfromgeometry_msgs.msgimportQuaternion# 绕九个点外围的8个目标点坐标waypoints[(1.5,1.5),(0.0,2.0),(-1.5,1.5),(-2.0,0.0),(-1.5,-1.5),(0.0,-2.0),(1.5,-1.5),(2.0,0.0),]defsend_goal(client,x,y):goalMoveBaseGoal()goal.target_pose.header.frame_idmapgoal.target_pose.header.stamprospy.Time.now()goal.target_pose.pose.position.xx goal.target_pose.pose.position.yy goal.target_pose.pose.position.z0.0# 注意必须设置完整四元数否则会报invalid quaterniongoal.target_pose.pose.orientationQuaternion(0.0,0.0,0.0,1.0)rospy.loginfo(f前往目标点: ({x},{y}))client.send_goal(goal)# 等待最多60秒到达目标点finishedclient.wait_for_result(rospy.Duration(60))iffinishedandclient.get_state()actionlib.GoalStatus.SUCCEEDED:rospy.loginfo(到达目标点)rospy.sleep(1.0)else:rospy.logwarn(未能到达目标点继续下一个)defmain():rospy.init_node(task3_circle)clientactionlib.SimpleActionClient(move_base,MoveBaseAction)rospy.loginfo(等待move_base服务...)client.wait_for_server()rospy.loginfo(等待3秒让导航系统准备好...)rospy.sleep(3.0)rospy.loginfo(开始绕圈)for(x,y)inwaypoints:send_goal(client,x,y)rospy.loginfo(绕圈完成)if__name____main__:main()保存后给脚本添加执行权限chmodx ~/scripts/task3_circle.py5.5 代码核心解析1. 四元数设置避坑点goal.target_pose.pose.orientationQuaternion(0.0,0.0,0.0,1.0)很多教程只写orientation.w 1.0会报错Aborting on goal because it was sent with an invalid quaternion。必须完整设置四元数 (x, y, z, w) (0, 0, 0, 1)表示朝向正前方。2. 等待机制finishedclient.wait_for_result(rospy.Duration(60))设置60秒超时避免某个点到不了导致整个脚本卡死。3. 顺序遍历for(x,y)inwaypoints:send_goal(client,x,y)依次发送8个目标点机器人完成一个再走下一个。4. 目标点坐标选取可能因为各版本有所不同地图方向和坐标位置可能略有区别可以自行在RViz中查看对应的绕桩坐标修改参数方法如下点击RViz顶部的Panels→ **Tool Properties**按钮鼠标移到RViz地图上窗口最底部便会显示类似这样的数字X: 1.234 Y: -0.567 Z: 0.0005.6 运行任务一需要3个终端# 终端1启动GazeboexportTURTLEBOT3_MODELburger roslaunch turtlebot3_gazebo turtlebot3_world.launch# 终端2启动导航exportTURTLEBOT3_MODELburger roslaunch turtlebot3_navigation turtlebot3_navigation.launch map_file:$HOME/map_world.yaml⚠️在RViz中用2D Pose Estimate设置好初始位置后# 终端3运行脚本python3 ~/scripts/task3_circle.py机器人会自动按顺序前往8个目标点完成绕桩一圈六、任务二自主避障TurtleBot3 House6.1 任务目标让机器人在 TurtleBot3 House 中不依赖地图仅靠激光雷达数据实时感知障碍物实现自主行走与避障。6.2 实现思路经典的反应式避障算法读取/scan话题获取360度激光雷达距离数据划分前/左/右三个扇区根据各扇区最近障碍距离做决策前方很近0.5m→ 停下向空的一侧旋转前方较近0.5~1m→ 减速并微转前方空旷1m→ 全速直走6.3 创建脚本gedit ~/scripts/task4_avoid.py粘贴以下代码#!/usr/bin/env python3importrospyfromsensor_msgs.msgimportLaserScanfromgeometry_msgs.msgimportTwistimportmathclassObstacleAvoider:def__init__(self):rospy.init_node(task4_avoid)# 发布速度指令self.cmd_pubrospy.Publisher(/cmd_vel,Twist,queue_size10)# 订阅激光雷达数据self.scan_subrospy.Subscriber(/scan,LaserScan,self.scan_callback)rospy.loginfo(避障节点启动)defget_min_range(self,ranges,start_deg,end_deg,total):根据角度范围获取最小距离start_idxint(start_deg/360.0*total)end_idxint(end_deg/360.0*total)sectorranges[start_idx:end_idx]# 过滤无效数据valid[rforrinsectorifnotmath.isnan(r)andnotmath.isinf(r)andr0.01]returnmin(valid)ifvalidelse999.0defscan_callback(self,scan):rangesscan.ranges totallen(ranges)# 前方扇区跨越0度需要分两段front_leftself.get_min_range(ranges,330,360,total)front_rightself.get_min_range(ranges,0,30,total)frontmin(front_left,front_right)# 左侧扇区60~120度leftself.get_min_range(ranges,60,120,total)# 右侧扇区240~300度rightself.get_min_range(ranges,240,300,total)rospy.loginfo(f左:{left:.2f}前:{front:.2f}右:{right:.2f})twistTwist()iffront0.5:# 前方有障碍停下转向空旷一侧twist.linear.x0.0ifleftright:twist.angular.z0.5rospy.loginfo(前方有障碍左转)else:twist.angular.z-0.5rospy.loginfo(前方有障碍右转)eliffront1.0:# 前方较近减速并微转twist.linear.x0.1twist.angular.z0.3ifleftrightelse-0.3rospy.loginfo(前方较近减速转向)else:# 前方空旷直走twist.linear.x0.2twist.angular.z0.0rospy.loginfo(前方空旷直走)self.cmd_pub.publish(twist)defrun(self):rospy.spin()if__name____main__:avoiderObstacleAvoider()avoider.run()保存后添加执行权限chmodx ~/scripts/task4_avoid.py6.4 代码核心解析1. 激光雷达扇区划分关键避坑点很多教程直接对ranges列表做切片如ranges[:total//4]但waffle_pi 的雷达0度正前方正前方扇区跨越了0度需要分两段读取front_leftself.get_min_range(ranges,330,360,total)# 左前方front_rightself.get_min_range(ranges,0,30,total)# 右前方frontmin(front_left,front_right)# 取两段最小值2. 无效数据过滤valid[rforrinsectorifnotmath.isnan(r)andnotmath.isinf(r)andr0.01]激光雷达可能返回nan、inf或 0必须过滤掉否则min()会返回错误结果。3. 三级避障策略前方距离行为线速度角速度 0.5m停下原地转0±0.50.5~1m减速微转0.1±0.3 1m全速直走0.204. 转向决策ifleftright:twist.angular.z0.5# 左边更空往左转正值else:twist.angular.z-0.5# 右边更空往右转负值ROS 中规定角速度正值逆时针左转负值顺时针右转。6.5 运行任务二# 终端1启动House场景exportTURTLEBOT3_MODELwaffle_pi roslaunch turtlebot3_gazebo turtlebot3_house.launch# 终端2运行避障脚本python3 ~/scripts/task4_avoid.py终端会持续打印距离信息[INFO] 左:1.23 前:2.45 右:1.67 [INFO] 前方空旷直走 [INFO] 左:0.89 前:0.42 右:1.12 [INFO] 前方有障碍右转七、常见问题排查7.1 报错Failed to create the dwa_local_planner原因缺少 dwa-local-planner 包解决sudoaptinstallros-noetic-dwa-local-planner7.2 报错Aborting on goal because it was sent with an invalid quaternion原因四元数设置不完整解决使用完整四元数fromgeometry_msgs.msgimportQuaternion goal.target_pose.pose.orientationQuaternion(0.0,0.0,0.0,1.0)7.3 dpkg被中断错误原因之前的安装被中断解决sudodpkg--configure-a 如果中途询问是否替换配置文件如vmtoolsd输入N保留原版本即可7.4 虚拟机网络故障详细排查重点很多同学装完后发现apt install报错暂时不能解析域名ping www.baidu.com也不通。这是因为虚拟机网卡没有正常工作。下面是完整排查步骤。7.4.1 先诊断网络状态ipaddriproute典型故障表现ens33网卡状态显示为DOWN没启用没有分配到 IP 地址看不到inet 192.168.x.x路由表完全为空7.4.2 修复方法一重启网络管理服务先试最简单的sudosystemctl restart NetworkManager等几秒后再检查ipaddriprouteping8.8.8.8如果ens33拿到了 IP出现inet 192.168.x.x且ping通了修复成功。7.4.3 修复方法二手动启用网卡如果方法一无效手动拉起网卡sudoiplinksetens33 upsudodhclient ens33然后再ip addr看是否拿到 IP。7.4.4 修复方法三检查VMware网络适配器设置如果ens33一直 DOWN 且 NetworkManager 拉不起来多半是虚拟机网络适配器被禁用了。操作步骤在 VMware 窗口右下角找到网络适配器图标小电脑形状右键 →连接确认有勾或者通过菜单操作虚拟机→设置→网络适配器确认已连接和启动时连接都打勾网络连接方式选NAT 模式最不容易出问题如果之前用的是自定义或仅主机模式先改成NAT试试改完之后回到虚拟机里再跑一遍sudosystemctl restart NetworkManageripaddrpingwww.baidu.com7.4.5 修复方法四重启VMware服务在Windows宿主机操作如果以上都不行在 Windows 上重启 VMware 的网络服务按Win R输入services.msc回车找到这两个服务分别右键→重新启动VMware NAT ServiceVMware DHCP Service然后回到Ubuntu虚拟机重新尝试上网7.4.6 修复方法五更换软件源如果网络正常但 ROS 源连不上换国内镜像源sudosh-cecho deb https://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu focal main /etc/apt/sources.list.d/ros-latest.listsudoaptupdate7.5 避障时机器人撞墙不转原因扇区角度划分错误没检测到前方障碍解决正前方0度跨越问题必须分两段读取雷达数据见 6.4 节7.6 导航目标点瞬间失败原因初始位置未设置或定位不准解决用2D Pose Estimate设置初始位置用键盘晃动机器人帮助 AMCL 收敛确认绿色粒子云已聚拢关闭键盘控制终端再运行脚本7.7 RViz 中地图区域空白原因Fixed Frame 设置错误解决在 RViz 左侧Global Options中把Fixed Frame从odom改为map导航时或base_footprint仅Gazebo时九、总结本教程完整覆盖了 TurtleBot3 仿真环境下的核心功能任务技术要点难度SLAM建图Gmapping算法⭐⭐自主导航move_base AMCL⭐⭐⭐绕桩巡航actionlib 多目标点⭐⭐⭐自主避障激光雷达 反应式控制⭐⭐⭐⭐完整代码已开源到 GitHubhttps://github.com/EnoXie422/turtlebot3-slam-navigation若本文对你有帮助欢迎点个 Star 支持一下⭐如果本文对你有帮助欢迎点赞、收藏、关注三连支持有问题欢迎评论区交流 本文标签#ROS#TurtleBot3#SLAM#自主导航#Gazebo仿真#机器人#避障算法