一个l4公司的面试
一面
讨论了自动驾驶参考线规划相关技术,包括换道方式、参考线生成、路径规划等内容,还进行了技术面试考查,具体如下:
🚗 参考线与换道技术
- 基础框架: 系统框架从阿波罗(Apollo)魔改而来,有基础版本。
- 换道方式:
- 原平行换道方式:换道距离长,路口连续换道困难。
- 新参考线直连方式:无 heading 回正过程,用贝塞尔曲线连接,拉长时距保证舒适性。
- 失败处理:实在换不过去只能去下一个路口掉头。
- 参考线生成:
- 有多种参考线,并行会生成自车所在车道、相邻车道及去目标车道参考线。
- 规划方式分纯平车道和拼接场景两种。
- 范围与自车位置及感知末端、地图引导点有关。
- 平滑处理:
- 用贝塞尔连出点链,放进平滑器优化成一条曲线。
- 若无动态障碍物,该曲线直接作为控车轨迹。
- 若有动态障碍物,在此基础上再做处理。
🗺️ 路径规划与决策
- 规划流程: 后续会进行决策(包括绕行、换道等),规划横向轨迹,再在其上做纵向决策(公共控制和解耦)。
- 绕行决策:
- 在参考线下游的路径决策层进行。
- 将障碍物 bounding box 投影到弗林纳(Frenet)坐标系。
- 根据其位置和侵入程度决策绕行方向和设置约束,用软约束建模到 QP。
- 软约束建模: 加松弛变量,在 Hession 上增广义维,松弛变量大小为软约束权重。满足约束时松弛变量为 0,不满足时在目标函数上加惩罚。
🚦 多态上下文与换道决策
- 参考线生成: 参考线一直生成,与换道不反馈。
- 换道执行: 换道时按 target 参考线直接换,换道前进行校验。
- 换道校验: 校验车道有无、目标几秒内有无障碍物、目标车道前后车之间空间是否足够,通过后生成轨迹。
面试官非常了解 Apollo 的框架,因此讲解的基于 Apollo 框架的内容都不感兴趣。
💻 技术面试考查
记事本 Coding
- 实现一个父类
parent。 - 父类要有一个虚函数,由子类实现。
- 在父类实现一个成员,这个成员子类可以访问。
- 实现一个二叉树节点。
- 以非递归的方式遍历二叉树。
C++ 基础
- 什么是前序遍历?
- 以左中右的顺序遍历二叉树(即中序遍历)。
- 讲解什么是
shared_ptr,什么是weak_ptr。 - 什么是
unordered_map?
二面
我还以为一面寄了,竟然今天和我约二面了!
以下是豆包总结
一、会议核心信息
| 项目 | 详情 |
|---|---|
| 会议主题 | CX835城市领航辅助驾驶项目横向规划算法工作汇报与技术面试 |
| 参会人员 | 汇报人(说话人A)、面试官(说话人B) |
| 会议时长 | 约40分钟 |
| 核心聚焦 | 横向规划算法(参考线生成、车道选择、轨迹优化等)的设计、实现与技术优化 |
二、核心工作成果
- 完成CX835项目横向规划算法核心模块开发,重点突破参考线生成技术,适配平车道、非结构化道路、疑难场景等多类工况。
- 提出轻地图与感知匹配的多版本迭代方案,解决非结构化道路参考线引导偏差问题,减少撞路沿、驶入对向车道等风险。
- 设计多状态机切换逻辑,实现平车道、入口、远端感知车道引导等状态的平滑过渡,保障路口通行稳定性。
- 构建动态障碍物绕行模块与LEDA异常情况处理模块,提升算法对复杂交通环境的适应性。
- 基于QP优化实现轨迹精调,通过硬约束+软约束结合的方式,平衡轨迹安全性与平滑性。
三、关键技术亮点
- 多场景参考线生成:平车道采用中心线平滑方案,非结构化道路采用三段式拼接(历史参考线+贝塞尔曲线+目标车道中心线),疑难场景采用专家轨迹模式。
- 轻地图与感知融合:迭代路沿匹配、道线宽度修正、对向停止线辅助三类方案,弥补轻地图精度不足的缺陷。
- 状态机智能切换:基于地图标识与感知结果,实现多状态自动切换,提前衔接目标车道,避免近端轨迹摆动。
- 横纵解耦+动态补全:参考线聚焦静态规划,通过下游绕行模块处理动态障碍物,兼顾规划效率与环境适应性。
四、面试官核心建议
- 表达优化:压缩自我介绍篇幅,突出核心成果,后续再展开细节讨论。
- 成果量化:补充算法优化的具体指标与数据(如横向偏差降低幅度、场景适配成功率等),增强成果说服力。
- 技术深化:
- 明确“画龙”“猛打方向”等问题的量化标准,结合方向盘转速、横向加加速度等物理量,通过数据埋点、影子模式构建闭环优化体系。
- 参考阿波罗框架中曲率约束的二阶差分项实现,完善轨迹优化的动力学约束设计。
- 数据驱动:针对路口等依赖地图的场景,探索数据驱动补全方案,提升算法对地图偏差的容错性。
五、coding
计算几何,判断一个点是否在多边形内,应该用射线法
但是我理解成了判断在凸多边形内,只判断了左右。
正确coding方法与思路
射线法的解析原理
射线法,也称为奇偶规则(Even-Odd Rule)或交叉数法,是判断点是否在多边形内部最常用、最直观的方法。
1. 核心思想:奇偶规则
其核心思想基于一个简单(但在数学上由“约当曲线定理”保证)的拓扑学事实:
从平面上的任意一点出发,画一条无限长的射线。如果该点在多边形(一个简单的闭合曲线)的内部,那么这条射线穿过(相交于)多边形边界的次数必定为奇数。
如果该点在多边形的外部,则射线穿过边界的次数必定为偶数(包括 0 次)。
一个简单的比喻:
想象多边形是一个围栏。
- 如果你仍在围栏内部,你向任意方向直线行走,要想到达围栏外(无限远处),你必须穿过围栏 1 次(奇数)。
- 如果你仍在围栏外部,你要么根本不会穿过围栏(0 次,偶数),要么你穿进去了(第 1 次),就必须再穿出来(第 2 次)才能到达无限远处。所以你总会穿过 0、2、4… 次(偶数)。
2. 算法实现:水平射线
为了简化计算,我们通常选择一条水平向右的射线。
给定一个点 P(x, y) 和一个多边形(由顶点 V1, V2, ... Vn 组成):
- 初始化一个交叉计数器
crossings = 0。 - 发射射线:从点
P出发,画一条y值不变、x向正无穷大(向右)的射线。 - 遍历多边形的每一条边:对于从
Vi到Vi+1的每条边:- 检查这条边是否与我们的水平射线相交。
- 统计交叉:如果相交,
crossings加 1。 - 判断结果:遍历完所有边后,检查
crossings的奇偶性。crossings % 2 == 1(奇数) 点在多边形内部。crossings % 2 == 0(偶数) 点在多边形外部。
3. 关键:处理特殊情况(边界情况)
简单地“计算交叉”在实践中是不可靠的,因为射线可能会“擦过”顶点或与水平边重合。一个健壮的算法必须精确定义什么是“有效交叉”:
-
射线与水平边重合:
- 问题:如果点
P的y坐标与多边形某条水平边的y坐标相同,射线可能与这条边重合,产生无限个交点。 - 解决方案:忽略所有水平边。水平边不构成“穿越”,它们不会使点从“内”变“外”。
- 问题:如果点
-
射线穿过顶点:
- 问题:如果射线恰好穿过一个顶点,它会同时与两条边(共享该顶点的边)接触。这可能导致被计数两次(偶数)或零次(偶数),即使它只是一次“穿越”。
- 解决方案:我们必须制定一个一致的规则来计算顶点。一个非常标准且稳健的规则是:
- 只计算那些端点
y坐标跨越了射线y坐标的边。 - 对于恰好落在射线上的顶点,我们将其视为属于某一条边。一个常见的约定是:只计算其
y坐标大于射线y坐标的那个端点(即,只把顶点当作其所在边的“上端点”时才计算)。 - 一个更简单的实现是:当一条边的两个端点一个
y值> p.y而另一个y值<= p.y时,我们才认为它可能与射线相交。这自动处理了顶点问题:- 如果射线穿过一个“凸”顶点(两条边都在射线同一侧),两条边都不会满足
(y1 > p.y)和(y2 <= p.y)的组合,所以不计数。 - 如果射线穿过一个“凹”顶点(两条边在射线两侧),只有一条边(向上跨越的或向下跨越的)会被计算,这是正确的。
- 如果射线与一个顶点相切(
p.y == vi.y),该顶点会被视为其所在边的“下端点”,也只会被计算一次。
- 如果射线穿过一个“凸”顶点(两条边都在射线同一侧),两条边都不会满足
- 只计算那些端点
1 | |
然后代码习惯需要注意,不修改的量应该传入常量引用。
三面
这是一场关于求职的技术面试会议。本次会议主要围绕候选人的工作经历、技术能力以及对新工作的期望展开讨论。面试官评估了候选人的编程技能和对自动驾驶规划算法的理解,并介绍了团队的技术方向和工作内容。
1、面试者背景介绍
面试者于2024年7月毕业后加入经纬恒润,担任CX 835项目中的算法工程师,主要负责横向规划模块中的参考线生成部分。
参考线是整套框架的基石,基于定位模块、导航地图和感知车道线信息生成,优化后形成平滑的参考线。
2、离职原因及求职期望
离职原因包括项目已交付,缺乏技术升级空间,以及出差时间过长(一年300多天中有180天出差)。
下一份工作期望待遇提升、减少出差频率,并希望接触端到端和时空联合规划等新技术框架。
3、技术讨论:端到端与时空联合规划
时空联合规划方案多基于采样方法,通过评分和优化生成轨迹;端到端方案存在数据不足和模型缺陷(如copycat问题)。
新公司端到端方案预计明年6月上线,面试者可参与场景迭代,但需依赖模型团队提供初版。
端到端技术需与robust框架结合,部分模块(如control)可能上游化。
4、出差频率与工作安排
新公司出差频率因岗位而异,核心骨干出差较多,特殊场景迭代时需出差,但无强制驻场开发要求。
5、编程能力考察
面试者实现了一个模板类队列(链表结构),讨论了链表与数组的区别及C++新特性(如右值引用、optional)。
1 | |
1 | |
对比以上内容,一个是指针,需要手动释放,一个是智能指针,不需要手动释放。
右值引用 vs 拷贝构造函数
核心概念
| 特性 | 右值引用 (T&&) |
拷贝构造函数 |
|---|---|---|
| 绑定对象 | 临时对象(右值) | 左值(具名对象) |
| 核心作用 | 移动语义(资源转移) | 深拷贝(创建独立副本) |
| 生命周期 | 延长临时对象生存期 | 无直接影响 |
| 典型场景 | 临时对象处理、容器优化 | 对象复制、返回值 |
右值引用工作机制
- 绑定规则
- 仅能绑定右值(临时对象、
std::move转换的左值) - 通过
T&&语法实现,避免拷贝开销
- 移动语义
1 | |
- 直接接管资源指针,源对象进入无效状态
拷贝构造函数演进
- 传统问题
- 浅拷贝风险:指针成员共享内存,导致双重释放
- 性能瓶颈:大对象深拷贝耗时(如
std::vector)
- 现代优化
- Rule of Five:自定义移动构造/赋值运算符
- 智能指针:
std::unique_ptr自动管理资源,避免手动深拷贝
关键代码对比
场景:字符串类资源管理
1 | |
- 拷贝构造:分配新内存并复制内容
- 移动构造:直接接管指针,源对象置空
性能对比与建议
| 指标 | 移动语义 | 拷贝构造 |
|---|---|---|
| 时间复杂度 | O(1)(仅指针操作) | O(n)(数据复制) |
| 内存分配 | 复用临时对象内存 | 需要新内存空间 |
| 适用场景 | 临时对象、资源回收 | 需要独立副本的场景 |
建议:
- 优先使用移动语义处理临时对象
- 对需持久化的对象使用拷贝构造
- 结合
std::move和std::forward实现完美转发
HR面
意向度:
很高,很靠前
薪资:
从底线往上给个区间,留有argue的余地
为什么看好新石器的机会
落地机会:全球最大的L4级无人城配(RoboVan)解决方案提供商。覆盖顺丰、京东等头部客户,赛道内的独角兽。而且从现在的趋势看,人力成本的提高,自动驾驶的普及,这种无人配送是大势所趋。
三面的时候的面试官提到过是主机厂,不是tier 1。全链路闭环能力,省去了很多tier 1和主机厂交互沟通的效率浪费。
面试官也都很厉害,技术平台上是有一个学习机会,上升空间。L4级自动驾驶全栈研发(感知-决策-控制),接触无图导航、多模态融合等核心技术。
现在是一个发展的上升期,可以和平台一同成长