
1. 三条路线怎么选先搞清楚你要的到底是什么很多人一上来就问“扫地机器人怎么做”其实这个问题本身就问错了。正确的问法是你想花多少钱、花多少时间、做到什么程度。这三个变量决定了你该走哪条路而不是反过来。我见过太多人一腔热血买了激光雷达和开发板结果卡在环境配置上三个月最后设备吃灰。也见过有人直接买现成方案两天就跑通了建图和导航然后在这个基础上慢慢改反而学得更多。所以第一步不是选硬件是选路线。1.1 路线一成品改造——最快看到效果的路这条路的逻辑很简单买一台市面上成熟的扫地机器人通过它的开放接口或者拆机接管控制权把原厂固件替换成你自己写的逻辑。适合想快速验证算法、不想从零搞硬件的人。具体怎么做市面上有些扫地机型号预留了串口调试接口你能直接读到激光雷达数据和轮子编码器数据也能直接发速度指令。你需要做的就是把它的通信协议逆向出来然后写一个桥接节点把数据转成ROS2的话题。这条路的优势非常明显底盘、电机、电池管理、充电桩全是现成的你不需要碰任何硬件设计。缺点也很明显你能改的东西有限传感器布局是固定的算力平台是焊死的想加个深度相机可能都没地方装。我实测下来这条路从零到跑通SLAM建图最快两天。前提是你得找到一台协议已经被社区摸透的型号。如果你选了一台冷门机器逆向协议可能就要花两周。注意拆机改造会失去保修而且不同批次的同型号机器可能用了不同的主控板。买之前一定要确认社区里有人成功改造过你手上这个具体批次。1.2 路线二套件组装——平衡学习深度和落地速度这条路的逻辑是买一套已经配好底盘、电机、雷达、算力板的套件自己负责组装和软件开发。适合想学ROS2和SLAM但不想在硬件选型和机械加工上耗太多时间的人。套件通常包含一个差速底盘带编码器电机、一个激光雷达2D或3D、一个算力板树莓派或者Jetson系列、一个电源管理模块。你拿到手之后需要自己接线、装ROS2、配置参数、写启动文件。这条路的核心工作量在软件侧。你需要理解ROS2的节点通信机制、TF变换树、URDF模型描述、Nav2的参数体系。硬件方面只需要按图接线不涉及焊接和机械设计。我个人的经验是这条路从开箱到跑通Nav2自主导航大概需要一到两周。时间主要花在调参上尤其是代价地图的参数和恢复行为的选择。但这个过程会让你真正理解导航栈是怎么工作的而不是只会按启动按钮。1.3 路线三从零攒机——最硬核也最自由这条路就是标题里说的“攒机路线图”。你需要自己选电机、自己设计底盘、自己画电路板、自己写底层驱动、自己搭ROS2环境。适合想彻底搞明白每一个环节或者有特殊需求比如超小体积、超强算力、特殊传感器的人。这条路的工作量是前两条路的五到十倍。你需要面对的问题包括但不限于电机选型扭矩够不够、编码器精度多少、电源设计电池电压、DCDC降压、电流余量、通信接口CAN还是串口、波特率多少、机械结构底盘尺寸、轮径、悬挂方式。但这条路的好处也是前两条路给不了的你对每一个参数都有完全的控制权。想让机器人跑多快就换多大轮子想加什么传感器就加什么接口想用什么算力平台就换什么板子。我建议只有在你已经有过至少一次路线一或路线二的经验之后再考虑从零攒机。否则你会在硬件问题和软件问题之间反复横跳根本分不清是电机没转还是ROS2节点没起来。1.4 三条路线的对比与选择建议对比维度路线一成品改造路线二套件组装路线三从零攒机上手时间1-3天1-2周1-3个月硬件工作量极低低极高软件工作量中中高极高学习深度浅中深总花费500-2000元2000-5000元3000-10000元可定制性低中极高适合人群算法验证学生/爱好者硬核玩家/创业者选哪条路取决于你现在处于什么阶段。如果你连ROS2都没装过我强烈建议先走路线一或路线二把建图和导航跑通一遍再决定要不要深入底层。2. 攒机路线图从电机选型到ROS2跑通这一章是给决定走路线三的人看的。我会按照实际攒机的时间顺序把每个环节的关键决策和踩坑点讲清楚。2.1 底盘与电机扭矩计算和编码器选择攒机的第一步不是买雷达是定底盘。底盘决定了你的机器人能跑多快、能爬多陡的坡、能载多重的设备。先算扭矩。假设你的机器人总重5kg轮子直径65mm想要最大速度0.5m/s加速度0.5m/s²。那么单个电机需要的扭矩是T (m * a * r) / (2 * n * η)其中m是总重a是加速度r是轮子半径n是电机数量η是传动效率直驱取0.9。代入数值T (5 * 0.5 * 0.0325) / (2 * 0.9) ≈ 0.045 N·m这只是加速需要的扭矩实际选型要留2-3倍余量所以选0.1-0.15 N·m的电机比较稳妥。市面上常见的JGB37-520减速电机减速比1:30的版本额定扭矩大约0.3 N·m完全够用。编码器方面必须选带霍尔编码器的电机精度至少11线每转11个脉冲。配合四倍频计数每转能读到44个脉冲。轮子转一圈走π×65≈204mm所以每个脉冲对应约4.6mm的位移。这个精度对于室内导航足够了。实操心得买电机的时候一定要问清楚编码器类型。有些便宜电机用的是电位器不是编码器用久了会漂移。霍尔编码器才是正道。2.2 主控与通信STM32做底层驱动底层驱动我推荐用STM32F103C8T6也就是常说的“蓝板”。原因很简单便宜、资料多、社区大、踩坑有人帮。STM32要干的事情包括读编码器脉冲、输出PWM控制电机、读IMU数据、通过串口和上位机通信。如果你用的是CAN总线还需要配置CAN外设。编码器读取用定时器的编码器模式最方便。以STM32F103为例TIM2和TIM3都支持编码器模式直接配置就行。注意编码器模式下的计数器是16位的会溢出需要在溢出中断里累加一个高位变量。PWM输出用TIM1或TIM4频率建议设在10kHz-20kHz之间。太低会有啸叫太高会有开关损耗。占空比分辨率用1000级就够了。串口通信的协议我建议自己定一个简单的帧格式比如帧头(0xAA 0x55) 长度 命令字 数据 校验和命令字包括设置速度、读取编码器、读取IMU、设置PID参数等。校验和用简单的累加取反就行不需要上CRC。注意STM32的串口波特率建议用115200或更高。如果你要传IMU数据115200可能不够建议上460800或921600。但波特率越高线材质量要求越高杜邦线可能扛不住。2.3 上位机与ROS2Ubuntu和ROS2版本选择上位机我推荐用树莓派4B4GB或8GB或者Jetson Orin Nano。树莓派便宜、功耗低、社区大但算力有限跑2D SLAM没问题跑3D SLAM或者视觉SLAM就吃力了。Jetson贵一些但算力强很多适合跑视觉SLAM或者深度学习模型。操作系统用Ubuntu 22.04 LTSROS2版本用Humble。这是目前最稳定的组合社区支持最好教程最多。不要用最新的Ubuntu 24.04和ROS2 Jazzy很多包还没适配你会遇到各种奇怪的编译错误。安装ROS2的步骤网上很多我只说几个容易踩坑的地方第一locale设置。ROS2对locale很敏感如果没设成UTF-8编译的时候会报各种奇怪的错误。执行sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALLen_US.UTF-8 LANGen_US.UTF-8 export LANGen_US.UTF-8第二源的选择。国内用官方源可能很慢建议换成国内镜像源。但注意有些镜像源同步不及时可能会缺包。如果遇到缺包换回官方源再试一次。第三rosdep初始化。这一步经常失败因为rosdep要访问外网。多试几次或者手动下载rosdep的配置文件放到本地。2.4 传感器选型2D雷达还是3D雷达2D激光雷达和3D激光雷达的区别就像手电筒和灯泡的区别。2D雷达只能扫一个平面3D雷达能扫一个锥形区域。对于扫地机器人来说2D雷达就够了。因为扫地机器人只需要知道地面附近的障碍物不需要知道天花板有多高。常见的2D雷达有思岚A1、镭神N10、杉川等价格从200到1000不等。如果你要做3D建图和导航那就需要3D雷达。但3D雷达的价格是2D雷达的五到十倍而且数据量大很多对算力要求也高。我建议先用2D雷达把SLAM和Nav2跑通再考虑升级3D。IMU方面必须有一个。因为轮式里程计在打滑或者碰撞时会漂移IMU可以提供角速度和加速度信息帮助融合定位。常见的IMU有MPU6050、ICM20948、BNO085等。MPU6050最便宜但精度一般BNO085最贵但自带融合算法输出直接就是姿态角。实操心得IMU的安装方向一定要和URDF里定义的一致。我见过有人把IMU装反了结果机器人一转向就飞车。装好之后先用ros2 topic echo看一下/imu/data的角速度符号对不对。3. SLAM建图从零到一张能用的地图SLAM是扫地机器人的核心能力。没有SLAM机器人就不知道自己在哪里也不知道障碍物在哪里。这一章讲怎么从零跑通SLAM建图。3.1 SLAM算法选型Gmapping还是CartographerROS2里常用的2D SLAM算法有两个Gmapping和Cartographer。Gmapping是基于粒子滤波的优点是计算量小、参数少、容易调缺点是建图面积大了之后粒子退化地图会漂。适合小面积100平米的室内环境。Cartographer是基于图优化的优点是建图面积大、回环检测强、地图一致性好缺点是计算量大、参数多、调参难。适合大面积100平米或者有多个房间的环境。我个人的建议是先用Gmapping把流程跑通再换Cartographer优化地图质量。因为Gmapping的参数就那么几个你很快就能看到效果建立信心。Cartographer的参数有几十个新手很容易调崩。Gmapping的核心参数参数名含义建议值maxUrange雷达最大使用距离雷达量程的80%sigma扫描匹配标准差0.05kernelSize扫描匹配搜索窗口1lstep线性搜索步长0.05astep角度搜索步长0.05iterations扫描匹配迭代次数5particles粒子数30-50delta地图分辨率0.05调参的顺序是先调maxUrange和sigma让扫描匹配能对上再调particles让地图不漂最后调delta控制地图精细度。3.2 建图实操从启动节点到保存地图假设你已经装好了ROS2 Humble和Gmapping雷达和底盘也都能正常发布话题。建图的步骤如下第一步启动雷达和底盘驱动。通常每个驱动包都会提供一个launch文件比如ros2 launch rplidar_ros rplidar.launch.py ros2 launch my_robot base.launch.py第二步启动Gmapping节点。你需要写一个launch文件把Gmapping的参数传进去from launch import LaunchDescription from launch_ros.actions import Node def generate_launch_description(): return LaunchDescription([ Node( packageslam_gmapping, executableslam_gmapping, nameslam_gmapping, parameters[{ maxUrange: 8.0, sigma: 0.05, particles: 40, delta: 0.05, base_frame: base_footprint, odom_frame: odom, map_frame: map, }], remappings[ (scan, /scan), ] ) ])第三步启动RViz2添加Map显示话题选/map。然后手动控制机器人走一圈或者用键盘遥控节点控制。ros2 run teleop_twist_keyboard teleop_twist_keyboard第四步走完之后保存地图ros2 run nav2_map_server map_saver_cli -f my_map这会生成my_map.pgm和my_map.yaml两个文件。pgm是地图图片yaml是地图元数据。注意建图的时候不要走太快也不要原地猛转。Gmapping的扫描匹配需要时间走太快会导致匹配失败地图会出现重影。建议线速度不超过0.3m/s角速度不超过0.5rad/s。3.3 地图质量优化常见问题与解决建出来的地图如果有问题通常表现为以下几种问题一墙壁有重影。原因是里程计漂移或者扫描匹配失败。解决办法是降低速度、增加粒子数、调大sigma。问题二地图有空洞。原因是雷达没扫到某些区域或者扫到了但匹配失败。解决办法是让机器人多角度扫几遍或者调大maxUrange。问题三地图整体歪斜。原因是IMU和雷达的外参标定不准或者里程计的比例因子不对。解决办法是重新标定外参或者调整里程计的比例因子。问题四回环处地图错位。这是Gmapping的固有问题因为Gmapping没有回环检测。解决办法是换Cartographer或者在回环处多走几遍让粒子收敛。我实测下来一个20平米的房间用Gmapping建图大概需要走5-10分钟地图质量可以接受。如果房间更大或者有长走廊建议直接上Cartographer。4. Nav2导航从地图到自主移动建好地图之后下一步就是让机器人在地图上自主导航。ROS2的导航栈叫Nav2是一个功能强大但参数复杂的系统。4.1 Nav2架构行为树和生命周期节点Nav2的核心是行为树Behavior Tree。行为树是一种任务调度机制把导航任务拆成一系列子任务比如“规划路径”、“跟随路径”、“恢复行为”等。每个子任务是一个节点节点之间通过状态成功、失败、运行中来切换。Nav2的另一个特点是生命周期节点Lifecycle Node。每个Nav2节点都有四个状态未配置、未激活、激活、已终结。节点启动后处于未配置状态需要手动配置和激活才能工作。这是为了让用户有机会在激活前修改参数。Nav2的主要节点包括节点名功能map_server加载和发布地图amcl蒙特卡洛定位planner_server全局路径规划controller_server局部路径规划和速度控制behavior_server恢复行为旋转、后退、等待bt_navigator行为树调度waypoint_follower多点导航启动Nav2的launch文件通常长这样ros2 launch nav2_bringup bringup_launch.py \ map:/path/to/my_map.yaml \ use_sim_time:false \ params_file:/path/to/nav2_params.yaml4.2 代价地图调参让机器人知道哪里能走代价地图Costmap是Nav2的核心数据结构它把地图上的每个格子赋予一个代价值代价值越高表示越不适合通行。代价地图分两层全局代价地图和局部代价地图。全局代价地图用于全局路径规划覆盖整个地图。局部代价地图用于局部路径规划只覆盖机器人周围一小块区域。代价地图的关键参数参数名含义建议值resolution分辨率0.05robot_radius机器人半径实际半径0.05inflation_radius膨胀半径机器人半径×2cost_scaling_factor代价衰减因子3.0obstacle_range障碍物检测距离3.0raytrace_range射线追踪距离3.5inflation_radius和cost_scaling_factor是最难调的两个参数。inflation_radius决定了障碍物周围多大范围内会有代价值cost_scaling_factor决定了代价值随距离衰减的速度。如果inflation_radius太小机器人会贴着墙走容易撞。如果太大机器人会不敢走窄通道。我建议从机器人半径的2倍开始试然后根据实际表现调整。实操心得调代价地图的时候在RViz2里把/global_costmap/costmap和/local_costmap/costmap都显示出来直观看到代价值的分布。红色是高代价蓝色是低代价黑色是致命障碍。4.3 行为树定制让导航更智能Nav2默认的行为树已经能处理大部分场景但如果你有特殊需求比如“先充电再导航”、“遇到障碍物先打电话通知”就需要定制行为树。行为树文件是XML格式的放在nav2_bt_navigator包的behavior_trees目录下。一个简单的行为树长这样root main_tree_to_executeMainTree BehaviorTree IDMainTree Sequence ComputePathToPose goal{goal} path{path}/ FollowPath path{path}/ /Sequence /BehaviorTree /root这个行为树只做了两件事规划路径、跟随路径。如果规划失败或者跟随失败整个行为树就失败了。更复杂的行为树会加入恢复行为root main_tree_to_executeMainTree BehaviorTree IDMainTree RecoveryNode number_of_retries3 Sequence ComputePathToPose goal{goal} path{path}/ FollowPath path{path}/ /Sequence Sequence ClearEntireCostmap/ Spin spin_dist1.57/ /Sequence /RecoveryNode /BehaviorTree /root这个行为树在失败时会清除代价地图并旋转一圈然后重试。最多重试3次。定制行为树需要理解每个节点的输入输出和状态转换。我建议先用默认行为树跑通再逐步替换节点不要一上来就自己写一个全新的。4.4 定位与重定位AMCL参数怎么调AMCL是蒙特卡洛定位算法它用粒子滤波来估计机器人在map坐标系下的位姿。AMCL的输入是激光雷达数据和里程计数据输出是map到odom的TF变换。AMCL的关键参数参数名含义建议值min_particles最小粒子数500max_particles最大粒子数2000pf_err粒子滤波误差0.05pf_z粒子滤波衰减0.99laser_max_range激光最大距离雷达量程的80%laser_min_range激光最小距离0.1update_min_d移动多少距离更新一次0.2update_min_a旋转多少角度更新一次0.2如果机器人定位漂移可以尝试增加粒子数、减小update_min_d和update_min_a、调大laser_max_range。如果机器人定位跳变可以尝试减小pf_err、调大pf_z。AMCL还有一个重要的功能是重定位。当机器人被搬动或者丢失定位时你可以在RViz2里用“2D Pose Estimate”按钮给它一个初始位姿AMCL会重新收敛。注意AMCL的初始位姿很重要。如果初始位姿差太远AMCL可能收敛到错误的位置。建议每次启动导航前都手动给一个大致准确的初始位姿。5. 常见问题与排查技巧实录这一章是我在实际攒机和调试过程中遇到的各种问题以及排查思路和解决方法。这些问题在官方文档里通常找不到但实际做的时候一定会遇到。5.1 硬件层问题电机不转、编码器读数异常问题电机不转但PWM有输出。排查步骤先用万用表量电机两端电压如果有电压但电机不转说明电机坏了或者线断了。如果没有电压说明驱动板没工作。检查驱动板的使能引脚是否拉高电源是否正常。问题编码器读数一直是0或者一直是最大值。排查步骤先用示波器看编码器的A相和B相有没有脉冲。如果没有脉冲说明编码器没供电或者坏了。如果有脉冲但STM32读不到说明定时器配置有问题。检查定时器的编码器模式是否使能GPIO是否配置为复用模式。问题电机转向和预期相反。解决方法交换电机两根线或者在代码里把PWM占空比取反。注意编码器的计数方向也要跟着改否则PID会正反馈。问题STM32的CAN通信突然连不上。排查步骤先检查CAN_H和CAN_L有没有接反终端电阻有没有接120欧姆。然后用示波器看CAN总线上的差分信号正常应该有2V左右的差分电压。如果信号正常但连不上检查波特率是否一致过滤器是否配置正确。5.2 软件层问题ROS2节点启动失败、话题不通问题ROS2节点启动时报“package not found”。解决方法先确认包是否安装ros2 pkg list | grep 包名。如果没有用apt安装或者从源码编译。如果安装了但还是找不到检查AMENT_PREFIX_PATH环境变量是否包含包的安装路径。问题话题发布了但收不到。排查步骤先用ros2 topic list确认话题存在。然后用ros2 topic info看发布者和订阅者的数量。如果发布者有但订阅者没有说明订阅者没启动或者话题名不匹配。如果都有但收不到数据用ros2 topic echo看有没有数据。问题TF变换报“Lookup would require extrapolation into the future”。原因是TF的时间戳不同步。检查所有发布TF的节点是否用了同一个时钟源。如果用了仿真时间确保use_sim_time参数一致。如果用了真实时间确保系统时间同步。问题Nav2启动后机器人不动。排查步骤先看/cmd_vel话题有没有数据。如果没有说明controller_server没工作。检查controller_server的插件是否加载代价地图是否收到激光数据。如果有数据但机器人不动检查底盘驱动是否订阅了/cmd_vel以及速度指令是否被限幅。5.3 调参层问题建图漂移、导航撞墙问题建图时地图漂移。原因通常是里程计不准或者扫描匹配失败。解决办法先标定里程计确保机器人走1米里程计读数也是1米左右。然后调Gmapping的sigma和particles让扫描匹配更稳定。问题导航时机器人撞墙。原因通常是代价地图的膨胀半径太小或者局部路径规划器的参数太激进。解决办法调大inflation_radius调小max_vel_theta和max_vel_x让机器人走慢一点。问题导航时机器人在原地转圈。原因通常是全局路径规划失败或者恢复行为被触发。检查全局代价地图是否收到了地图数据全局路径规划器的插件是否加载。如果地图没问题检查目标点是否在障碍物里面。问题导航时机器人走一半停住。原因通常是局部路径规划失败或者代价地图被障碍物填满。检查局部代价地图的obstacle_range和raytrace_range确保能清除已经不在的障碍物。5.4 常见问题速查表现象可能原因排查方法解决方法电机不转驱动板没使能量驱动板使能引脚拉高使能引脚编码器读数为0编码器没供电量编码器电源接上电源CAN连不上终端电阻没接量CAN_H和CAN_L之间电阻接120欧姆电阻ROS2包找不到环境变量没sourceecho $AMENT_PREFIX_PATHsource install/setup.bash话题收不到话题名不匹配ros2 topic info检查remappingTF报错时间戳不同步ros2 topic echo /tf统一时钟源建图漂移里程计不准手动推1米看读数标定里程计导航撞墙膨胀半径太小看代价地图调大inflation_radius原地转圈全局规划失败看全局代价地图检查地图和目标点走一半停住局部规划失败看局部代价地图调大obstacle_range5.5 独家避坑技巧技巧一先跑仿真再上真机。Gazebo里跑通了再上真机能省很多硬件调试的时间。Gazebo的物理引擎虽然不完美但足以验证算法逻辑。技巧二用rosbag记录数据。每次调试都录一个rosbag出问题的时候可以回放不用重新跑一遍。ros2 bag record -a录所有话题ros2 bag play回放。技巧三参数用YAML文件管理。不要硬编码在代码里用YAML文件管理方便修改和版本控制。Nav2的参数文件就是一个很好的例子。技巧四分模块调试。不要一次性启动所有节点一个模块一个模块地启动确认每个模块都正常再启动下一个。这样出问题的时候容易定位。技巧五多看日志。ROS2的日志级别可以调整--ros-args --log-level debug能看到更多信息。很多问题日志里已经有提示只是你没注意。技巧六善用RViz2。RViz2不只是可视化工具也是调试工具。把TF、代价地图、路径、激光数据都显示出来一眼就能看出哪里不对。技巧七加入社区。ROS2的社区很活跃遇到问题先搜一下大概率有人遇到过。但提问的时候要提供足够的信息系统版本、ROS2版本、完整报错、已经尝试过的解决方法。攒一台扫地机器人这件事说难也难说简单也简单。难的是每个环节都有坑简单的是每个坑都有人踩过。我自己的经验是不要追求一次做完美先跑通再优化。第一版能建图能导航就行哪怕地图歪一点、导航慢一点。跑通之后你就有信心了然后再逐个模块优化。最后分享一个小技巧如果你在调Nav2的时候卡住了先把所有参数恢复默认只改robot_radius和inflation_radius其他都别动。这两个参数对了导航基本就能跑。其他的参数都是锦上添花不是雪中送炭。