一、ROS核心机制(3题)

第1题:请对比ROS 1和ROS 2的核心差异,重点说说当中Master机制的变化以及为什么要这么改?

考察点: ROS框架底层理解、架构演进认知

答案解析:

面试官问这个问题,是想看你对ROS体系有没有深度认知,不是单纯背概念。

先说最关键的——Master没了。ROS 1依赖一个叫roscore的中央节点来做"通讯录",所有节点启动后先去Master注册,Publisher要发布话题得先问Master"谁订了这个话题?",Master告诉它Subscriber的地址,两边才能建连。这就带来几个致命问题:单点故障(Master挂了整个系统崩)、无法跨网络(Master必须统一发现)、没有安全性(谁都能连)。

ROS 2改用了DDS(Data Distribution Service) 作为底层通信中间件。DDS自带分布式发现机制,每个节点启动后通过DDS的Discovery协议自己去发现其他节点,不需要中央节点。这就彻底解决了单点故障,而且DDS原生支持QoS(服务质量配置,比如可靠传输、超时等),也支持跨网络通信和安全加密。

再补充几个重要差异:

  • 实时性: ROS 1走TCPROS/UDPROS,没有实时保证;ROS 2基于DDS可以配置实时策略,满足工业级需求

  • 跨平台: ROS 2支持Windows、macOS、RTOS,ROS 1只支持Linux

  • Python版本: ROS 1用Python 2,ROS 2至少Python 3.5+

  • Launch文件: ROS 1的launch是XML,表达能力有限;ROS 2改成Python脚本,可以做条件判断、参数计算等复杂逻辑

说到小米,有个很有意思的背景——小米CyberDog(铁蛋)项目在2020年技术选型时,团队内部对用ROS 1还是ROS 2争论了很久。ROS 1生态更成熟,但当时还是二号员工的徐海望力排众议坚持用ROS 2,因为看好它的设计理念——工业化的开发、部署、维护。为了说服大家,他还帮不同方向的同事解决ROS 2的学习问题和bug。小米是国内最早采用ROS 2路线的团队之一,这在面试中提到会很加分。


第2题:请详细解释ROS 2的三种通信方式——Topic、Service、Action,各自适合什么场景?给个实际例子。

考察点: 通信机制理解、场景判断力

答案解析:

这道题几乎是ROS面试必问,但区别在于你能不能说清楚"为什么要有三种"以及"什么时候选哪个"。

Topic(话题): 发布/订阅模式,单向、异步、一对多。Publisher发数据到某个话题上,所有订阅了这个话题的节点都能收到。适合高频、持续的数据流,比如激光雷达的点云数据、IMU的加速度数据、相机的图像流。为什么不用Service?因为传感器数据一秒可能有10次、20次、甚至100次,如果用Service的请求-响应模式,CPU全浪费在握手上了。Topic的设计理念就是"发送端不管接收端是谁",解耦性最好。

Service(服务): 请求/响应模式,双向、同步。客户端发请求,服务端处理完后返回结果,这个过程中客户端会阻塞等待。适合一次性、需要确认结果的场景,比如"打开相机"、"切换到导航模式"、"查询机器人当前电量"。典型的例子是小车上的"急停服务"——上层发一个Stop请求,底层收到后立刻刹车并返回确认。

Action(动作): 双向、异步、带反馈。Action本质上是Service的升级版。Service有硬伤——如果服务端需要执行很长时间(比如让机器人从A点走到B点),客户端会一直等在那儿,既不知道进度也取消不了。Action在Service的request/response基础上增加了feedback(中间反馈) 和cancel(取消)机制。适合长时间执行且需要进度反馈的任务,比如导航("当前走到了30%的位置")、机械臂抓取("手臂正在下降")。

一句话总结: 传感器流用Topic,查询/触发用Service,长时间任务用Action。


第3题:什么是ROS 2的QoS(Quality of Service)配置?在CyberDog这样的四足机器人上,传感器数据和运动控制指令分别该怎么配QoS?

考察点: ROS 2高阶特性、工程实践

答案解析:

这道题区分度很高,只会用默认QoS的人答不上来。

QoS是ROS 2基于DDS层提供的一套通信质量配置参数,让你可以精细控制消息的传输行为。核心配置项包括:

  • Reliability(可靠性): RELIABLE(保证送达,会重传)vs BEST_EFFORT(尽力送达,丢了不重传)

  • Durability(持久性): TRANSIENT_LOCAL(晚订阅也能收到最后一条消息)vs VOLATILE(只收订阅后的消息)

  • Deadline(截止时间): 要求消息在指定时间内送达

  • Liveliness(活性): 检测节点是否还活着

  • History(历史深度): 保留最近N条消息还是全部

在CyberDog这类四足机器人上的典型配置:

激光雷达/深度相机数据 → BEST_EFFORT + VOLATILE

  • 点云数据量极大,一秒几十万点,追求Reliable的话网络会炸

  • 丢掉一两帧没关系,下一帧马上来,机器人运动很慢,传感器速度远快于场景变化

  • 用BEST_EFFORT保证低延迟

摄像头图像 → BEST_EFFORT + VOLATILE

  • 类似理由,图像数据量大,追求实时性不追求局部丢帧

运动控制指令(cmd_vel) → RELIABLE + VOLATILE

  • 控制指令绝对不能丢,丢了机器人可能撞墙

  • 每条都必须送达,所以必须Reliable

  • 但不需要持久性,每次都发最新的就行

地图数据(map) → RELIABLE + TRANSIENT_LOCAL

  • 地图数据建好后基本不变,后面启动的节点也需要加载

  • TRANSIENT_LOCAL保证晚订阅的节点也能收到整张地图

面试技巧: 如果能结合CyberDog的实际场景说,比如"四足机器人在奔跑时全身12个关节的关节状态数据用BEST_EFFORT发布,因为频率高且丢一帧不影响控制",就很加分。


二、TF变换与导航栈(3题)

第4题:请解释ROS中TF(坐标变换)树的概念。对于一台装有激光雷达的移动机器人,TF树长什么样?map→odom→base_link这三个坐标系是干什么的?

考察点: TF机制理解、导航基础

答案解析:

TF(Transform)是ROS里管理坐标系变换的核心库(ROS 2里是TF2)。机器人身上有各种"坐标系"——机器人的中心叫base_link,激光雷达有自己的坐标系,相机有自己的坐标系,地图也有坐标系。机器人在移动,这些坐标系之间的相对关系在变化,TF就是维护这棵"坐标系关系树"的。

一个典型的移动机器人TF树:

暂时无法在飞书文档外展示此内容

三个核心坐标系的含义:

map(地图坐标系): 固定坐标系,一般是启动时确定的全局坐标原点。它是"绝对参考系"——机器人在世界上的真实位置用map坐标表示。日常不会变。

odom(里程计坐标系): 也是固定坐标系,由里程计驱动维护。它和map的关系是:map→odom的变换由定位模块(比如AMCL或SLAM)持续修正。为什么需要这个中间层?因为里程计会漂移(轮子打滑、IMU误差),但里程计的短期精度很高。odom是"局部平滑的",map是"全局准确的"。这层"双坐标系结构"让导航系统能同时利用里程计的局部平滑性和地图的全局一致性。

base_link(机器人基坐标系): 跟随机器的坐标系,原点一般在机器人底盘中心。所有传感器都相对于base_link定义位置。

核心机制:

  • map→odom:由定位模块(AMCL/SLAM)发布,慢更新但准确,修正里程计漂移

  • odom→base_link:由里程计系统(轮式编码器+IMU融合)发布,快更新但会漂移

  • base_link→sensor:静态变换,在URDF里定义,表示传感器装在机器人什么位置

面试官还想听到你理解"为什么要有map和odom两层"——这是REP 105标准规定的,目的是解耦全局定位和局部里程计的更新频率差异。


第5题:Nav2导航栈的核心构成模块有哪些?从"接到一个导航目标点到机器人到达"的完整流程是怎样的?

考察点: Navigation Stack架构理解、工程实践

答案解析:

Nav2是ROS 2下官方导航框架,接到目标点到实际到达,大致流程如下:

第一步:全局路径规划(Global Planner)

  • 收到目标点后,全局规划器(默认是Navfn或Smac Planner)在全局代价地图上规划一条从当前位置到目标点的路径

  • 全局代价地图由静态地图层(事先建好的地图)+ 障碍物层组成

  • 输出是一条粗糙的全局路径,用A*或Dijkstra算法

第二步:局部路径规划与跟随(Local Planner)

  • 机器人开始沿着全局路径移动,但只走一小段(比如前方3-5米范围内)

  • 局部规划器(默认是Regulated Pure Pursuit或DWB)在局部代价地图上实时规划

  • 局部代价地图更新频率高,包含激光雷达/深度相机检测到的动态障碍物

  • 输出是速度指令(线速度+角速度),发布到cmd_vel话题

第三步:行为树控制(Behavior Tree)

  • Nav2用行为树管理导航生命周期,包括"规划→控制→恢复"的决策逻辑

  • 如果局部规划器发现走不通(比如前方突然出现一个人),行为树会触发"恢复行为"——比如先停止、后退、旋转再重新规划

  • 如果多次重试失败,返回导航失败状态

第四步:定位持续修正

  • 整个过程中,AMCL(自适应蒙特卡罗定位)一直在运行

  • 它用粒子滤波器将雷达数据和静态地图做匹配,持续修正map→odom的变换

  • 这保证了机器人知道自己"到底在哪儿"

核心模块总结:

| 模块 | 功能 |

|------|------|

| AMCL | 粒子滤波定位,输出map→odom TF |

| Planner | A*/Dijkstra全局路径规划 |

| Controller | DWB/Regulated Pure Pursuit局部控制 |

| Costmap | 代价地图(全局+局部),多层感知障碍物 |

| Behavior Tree | 导航决策逻辑编排 |

| Recoveries | 旋转、后退等恢复行为 |

| Map Server | 加载/提供静态地图 |


第6题:AMCL定位的原理是什么?它在系统中负责什么?粒子收敛后,遇到"机器人绑架问题"(Kidnapped Robot Problem)怎么办?

考察点: 定位算法理解、异常处理

答案解析:

AMCL是"自适应蒙特卡罗定位"的缩写,是Nav2标配的二维定位算法。

原理:

  • 在全局地图上"撒"大量粒子,每个粒子代表机器人可能的一个位置和朝向(即一个位姿假设)

  • 初始时,粒子均匀散布在整个地图上,或者集中在已知的初始位姿周围

  • 机器人移动后,通过运动模型给每个粒子更新位置

  • 拿到雷达扫描数据后,计算每个粒子位置的"观测似然"——也就是"如果机器人真在这个位置,雷达看到的环境应该长这样,跟实际扫描像不像?"

  • 粒子滤波器的"重采样"步骤:高分粒子(像真的)被保留甚至复制,低分粒子被淘汰

  • 经过几轮迭代,粒子在真正的位置附近"收敛",形成一个集中的粒子簇

  • "自适应"体现在:粒子数不是固定的,当定位很确定时可以减少粒子(省算力),不确定时自动增加粒子

AMCL在系统中的职责:

  • 输出map→odom的TF变换

  • 它接收:雷达扫描数据、地图、里程计数据、初始位姿

  • 它堵的是"里程计漂移"的窟窿——轮式里程计短期准但长期飘,AMCL用地图修正这个漂移

机器人绑架问题(Kidnapped Robot Problem):

这是定位算法最难解决的问题之一。场景:机器人正常导航中,突然被人抱起来放到另一个位置。AMCL的粒子还集中在原位置,但实际位置变了,定位就丢了。

AMCL处理绑架的方式:

  1. 随机注入新粒子: 在每次重采样时,会随机在地图其他地方注入一小部分粒子(默认约0.01-0.05的比例)

  2. 差分布: 如果连续几帧观测到"所有现有粒子的观测似然都很低,但某个新粒子突然拿高分",说明被绑架了,系统会快速收敛到新位置

  3. 参数调节: recovery_alpha_slow和recovery_alpha_fast两个参数控制了粒子退化速度的监测——当快速退化远大于慢速退化时,说明定位可能在崩,自动增加随机粒子

面试加分: 可以提一下在CyberDog这样四足机器人上,运动模型比轮式机器人更复杂——四足机器人走路有"弹跳""震动",里程计噪声更大,AMCL的参数需要特殊调校。


三、仿真与URDF(2题)

第7题:请手写一个大致的URDF文件结构,描述一个带有激光雷达的两轮差速机器人,需要包含哪些关键元素?joint的类型如何选择?

考察点: URDF建模能力、对机器人运动学的理解

答案解析:

URDF(Unified Robot Description Format)是用XML描述机器人模型的格式。面试官让你手写URDF,目的是看你知道一个完整机器人描述包含什么,以及你对"刚体"和"关节"两个核心概念的理解。

一个典型的两轮差速小车URDF骨架(重点展示关键部分):

暂时无法在飞书文档外展示此内容

Joint类型选择:

| 类型 | 说明 | 适用场景 |

| fixed | 固定连接,两个link间无相对运动 | 激光雷达、相机等传感器支架 |

| revolute | 旋转关节,有限角度范围 | 机械臂肘关节(-90°~90°) |

| continuous | 连续旋转关节,无角度限制 | 车轮、四足机器人髋关节 |

| prismatic | 滑动关节,沿一个轴直线运动 | 伸缩臂、电梯机构 |

| planar | 平面关节,2D平移+1个旋转 | 很少用 |

| floating | 6自由度浮动关节 | 很少用,一般用TF替代 |

面试Tips:

  • 别忘了inertial标签——Gazebo仿真需要质量+惯性矩阵,否则物理引擎报warning

  • collision和visual可以不同,比如用简单形状做碰撞检测,复杂模型做可视化

  • 描述四足机器人时,每条腿至少3个关节(hip/ thigh/calf),关节类型分别是continuous(hip旋转轴)、revolute(大腿前后摆)、revolute(小腿前后摆)


第8题:你在做Gazebo仿真的时候遇到过哪些坑?怎么把一台在Gazebo里跑得好好的机器人模型,正确部署到小米CyberDog这种真实机器上?

考察点: 仿真→真实迁移(Sim2Real)经验、工程问题解决能力

答案解析:

这道题面试官想听你踩过的坑,不是背诵知识点。说真话最打动人。

Gazebo常见坑:

1. 物理参数不对导致机器人"飞天"或"钻地"

  • 惯性矩阵算错了,机器人一启动就抽风。解决方案:核对SolidWorks/Onshape导出数据和URDF里的inertial值是否一致

  • mu1、mu2摩擦系数设得太小,机器人原地打滑走不动;设得太大,转弯甩不过来

  • 悬架刚度(stiffness / damping)不对,车体一直在抖

2. PID参数在仿真和真机上天差地别

  • 仿真里的电机模型太理想,PID随便调就稳。上真机后同样的P值会导致振荡甚至电机烧掉

  • 解决方案:仿真中故意加入噪声和延迟,或者用"先调D、再调P、最后调I"的顺序

3. 传感器噪声模型设置不当

  • 仿真里雷达扫描"完美"无噪声,上真机后完全定位不准

  • 应该在Gazebo里给激光雷达配置高斯噪声,模拟真实传感器的测量误差

仿真→真实迁移的关键步骤:

第一步:硬件抽象层替换

  • 仿真中机器人通过diff_drive_controller和gazebo_ros_control与物理世界交互

  • 上真机后,这部分要换成真实的电机驱动节点,通过CAN总线或串口跟电机通信

  • 硬件抽象层(HAL)要设计好接口——控制指令格式、反馈数据解析

第二步:Sensor驱动替换

  • 仿真中的雷达数据来自gazebo_ros_laser插件,上真机后换用真实雷达厂商的ROS驱动

  • 注意frame_id要一致,如果真机雷达的坐标系和仿真里不同,TF就会错乱

第三步:参数标定

  • 里程计参数(编码器线数、轮子直径、轮距)必须和真实硬件严格一致,否则TF和odom全错

  • 关节限位(soft_limits)要跟实际电机行程匹配

  • IMU的安装方向、零偏值需要实际标定

第四步:网络和延迟适配

  • 仿真里所有节点在同一台机器上,没有网络延迟

  • 真机上控制节点在板载计算机、电机驱动在MCU、视觉处理可能在另一台设备,网络延迟变了

  • QoS参数可能需要从BEST_EFFORT改成RELIABLE或者调整Deadline

第五步:逐步替换,分模块验证

  • 不要"一把梭"全部替换到真机

  • 建议顺序:底盘驱动验证 → 里程计验证 → 雷达驱动验证 → 定位验证 → 导航验证 → 完整功能验证

  • 每替换一个模块,都在真机上跑一遍基础测试

说到小米: CyberDog团队当初在仿真→真机迁移中也踩了不少坑,比如ROS 2早期版本在WiFi切换时会崩溃(从WiFi切到手机热点),团队花了一天一夜从底层改DDS源码才解决。这种"踩坑→解决"的故事,在面试中说出来非常加分。


四、系统设计(2题)

第9题:如果要你在CyberDog四足机器人上设计一个"自主跟随"功能(人走到哪狗跟到哪),请画出完整的ROS节点/话题架构并说明数据流。

考察点: 系统设计能力、架构思考、工程落地

答案解析:

这道题是开放题,没有标准答案,但面试官看的是你的"架构感"——能不能把感知、决策、控制串起来。

完整架构设计:

暂时无法在飞书文档外展示此内容

数据流说明:

  1. 感知阶段: 深度相机数据→YOLOv8检测到人→输出人的2D框→逆投影到3D空间得到人的位置(PointStamped);同时激光雷达数据被用于障碍物级+人的辅助追踪

  2. 追踪阶段: PersonTrackNode用卡尔曼滤波对目标位置做平滑、预测,消除检测抖动和偶然漏检

  3. 决策阶段: FollowBehaviorNode维护一个"期望跟随距离"(如1.5米),根据实际距离计算目标点——人在前方1.5米处就是目标点,保持人和机器人的相对方向

  4. 导航阶段: 调用Nav2的NavigateToPose Action,把/follow_goal传给Nav2。关键点:目标要持续更新,但不能太频繁(否则路径规划一直在重新算),每秒刷新2-3次比较合理

  5. 恢复机制: 如果跟丢目标(连续5秒没检测到人),启动"原地旋转搜索"模式;如果超过10秒还是找不到,停止并上报状态

需要重点考虑的Edge Cases:

  • 人被遮挡时怎么处理 → 结合卡尔曼预测状态保持跟随

  • 人突然转向时响应速度 → 通过预测+方向变化检测提前响应

  • 前方有障碍物时是否绕行 → Nav2自带避障,但需要调整"与人保持安全距离"的规划参数

  • 楼梯/斜坡等复杂地形 → 四足机器人通过性比轮式好,但可能需要切换步态


五、场景应用(1题)

第10题:你在实际ROS开发过程中,遇到过一个印象最深的技术难题,你是怎么一步一步定位并解决的?

考察点: 实际问题排查能力、工程经验、系统性思维

答案解析:

这道题面试官其实不是在问技术细节,而是在考察你的故障排查方法论。建议用"STAR法则"(Situation-Task-Action-Result)来讲。

可以参考的思路(以一个实际难题为例):

问题背景: 一个四足机器人在跑步模式下,每隔几分钟会出现一次"突然跛行"——某条腿动作异常,持续几百毫秒后恢复。传统方法加日志很难捕捉。

排查过程(由易到难):

Step 1:确定是硬件还是软件问题

  • 先跑简单的"单腿画圈"测试,确认关节电机和编码器本身没问题

  • 用示波器抓电机端的CAN数据,信号正常

  • 排除硬件故障

Step 2:定位到ROS 2通信卡顿

  • 用ros2 topic hz和ros2 topic delay监控关节控制话题的频率和延迟

  • 发现异常时刻:关节控制话题的发布频率从正常的500Hz突然掉到200Hz

  • 进一步用ros2 topic bw查看带宽占用

Step 3:追根溯源到QoS堵塞

  • 发现原因是某一路传感器数据量暴涨(比如深度相机在强光下输出异常多的点云)

  • 这条高速传感器话题吃了大量DDS缓冲区,影响了Control指令的传输

  • 传感器和控制话题在同一Network Partition里

解决方案:

  1. 分离资源: 将传感器数据和控制指令放在不同的DDS分区(Partition),保证控制通道不受影响

  2. 调整QoS: 传感器话题改用BEST_EFFORT降低带宽占用;控制话题用RELIABLE+设置Depth=1(只保留最新一条)

  3. 添加保护机制: 在传感器节点中增加"流量整形"——如果传感器数据超过阈值,自动降采样

  4. 增加监控: 添加/system_status话题,定期发布各节点的CPU占用、内存、话题延迟等健康数据

复盘总结(面试官想听的部分):

  • 排查时要"先怀疑自己、再怀疑别人、最后才怀疑硬件"

  • 善用ROS 2的调试工具链:rqt_graph看拓扑、ros2 topic hz/delay/bw做定量的通信分析

  • 四足机器人对实时性要求极高,500Hz的关节控制频率下,任何通信延迟都会导致"跛行"

  • 学到的一点:不要迷信DDS的默认配置,一定要根据实际场景调优QoS

面试注意: 如果没做过四足机器人,可以说一个类似的ROS项目排故经历,关键是要有"定位过程"和"方法论总结",而不是只讲现象不分析。


总结

小米作为国内最早采用ROS 2路线的机器人团队之一,从CyberDog到CyberOne,面试中非常看重:

  1. 工程实践能力 — 不止于"会调包",要看你能不能独立搭建系统、解决实际问题

  2. 底层理解 — ROS 2的DDS、QoS、TF、生命周期管理这些如果你只会表层,大概率被淘汰

  3. 系统思维 — 能不能把感知→决策→控制串起来,能不能识别架构层面的问题

  4. 踩坑经验 — 面试官更愿意听你"遇到什么困难怎么解决"的故事,而不只是背八股

祝面试顺利!

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐