
车载AVM动态倒车轨迹线绘制算法
动态随动轨迹线是360全景环视(AVM)、倒车影像核心辅助功能,可实时根据方向盘转角预测车辆行驶包络线,降低剐蹭风险。
本文从底层阿克曼转向运动学理论切入,完整拆解轨迹点生成数学推导、坐标转换、图像渲染全流程;对比当下车载行业实时几何计算、查表预计算、高阶平滑规划三大主流实现方案;配套完整可运行仿真代码逐行解析,兼顾算法理论深度与工程落地实操,适合车载HMI、环视视觉开发人员直接发布参考。
一、行业背景与轨迹线分类
1.1 轨迹线功能价值
低速倒车、挪车场景下,驾驶员无法直观判断车轮与车身外侧行驶路径,动态轨迹线将车辆未来行驶轨迹以彩色线条叠加在摄像头画面上层,区分车轮轨迹、车身安全边界、距离标尺,是乘用车标配安全功能。

1.2 两类主流轨迹方案
- 静态固定轨迹(低端后视摄像头)
无方向盘转角信号输入,轨迹弧线固定不变,仅作粗略参考,无实时性,已逐步淘汰。 - 动态随动轨迹(中高端AVM全景主流)
CAN总线实时读取方向盘转角,毫秒级更新轨迹曲线,精准匹配车辆转向姿态,本文重点讲解该方案底层算法。
1.3 车载系统完整数据流
方向盘转角传感器 → 车机MCU/视觉SOC → 阿克曼几何计算世界轨迹点 → 相机IPM逆透视投影/鱼眼畸变矫正 → 图像像素坐标转换 → GPU叠加渲染线条输出屏幕。
二、底层核心:阿克曼转向运动学模型

2.1 模型基础定义(车辆固有参数)
| 参数 | 符号 | 说明 | 家用轿车典型值 |
|---|---|---|---|
| 轴距 | LLL | 前后轴中心点纵向距离 | 2.7m |
| 轮距 | WWW | 左右后轮横向间距 | 1.8m |
| 半轮距 | W/2W/2W/2 | 后轴中点到单侧车轮距离 | 0.9m |
| 前轮等效转角 | δ\deltaδ | 方向盘转角换算前轮倾斜角度,rad | ±35°最大 |
| 瞬时转向半径 | RRR | 后轴中心绕ICR转弯半径 | 3.5~6m |
| ICR瞬时转向中心 | OOO | 四轮纯滚动共同圆心 | 左转(-R,0),右转(R,0) |
2.2 转弯半径核心公式推导
车辆转弯时四轮绕同一瞬时圆心纯滚动,由直角三角几何关系得后轴中心转弯半径:
R=LtanδR = \frac{L}{\tan\delta}R=tanδL
- 方向盘回正 δ≈0\delta≈0δ≈0,tanδ→0\tan\delta→0tanδ→0,R→∞R→∞R→∞,车辆直行;
- 方向盘打死 δ\deltaδ 最大,RRR 最小,转弯弧度最急。
2.3 统一坐标系约定(代码标准坐标系)
以后轴中心点 为世界坐标系原点(0,0)(0,0)(0,0):
- +Y+Y+Y:车辆车头前进方向(倒车Y值减小);
- −X-X−X:车辆左侧,+X+X+X:车辆右侧;
- 地面所有轨迹点均基于该二维平面计算,无高度维度(仅考虑地面行驶)。
2.4 圆弧轨迹点生成数学模型(弧长极坐标法)
2.4.1 弧长与圆心角转换公式
车辆沿圆弧向前行驶地面距离sss(弧长),绕ICR圆心转过弧度角θ\thetaθ:
θ=sR\theta = \frac{s}{R}θ=Rs
相比传统"已知y解方程求x"的开根号方案,极坐标三角函数法无开方运算,嵌入式设备算力开销更低,点间距均匀、曲线顺滑,是车载行业标准采样方式。
2.4.2 左转/右转轨迹坐标方程
-
左转(δ>0\delta>0δ>0,ICR圆心O(−R,0)O(-R,0)O(−R,0))
后轴中心轨迹:
{xcenter=−R+R⋅cosθycenter=R⋅sinθ \begin{cases} x_{center} = -R + R\cdot\cos\theta \\ y_{center} = R\cdot\sin\theta \end{cases} {xcenter=−R+R⋅cosθycenter=R⋅sinθ
左轮(内侧轮,转弯半径R−W/2R-W/2R−W/2):
{xleft=−R+(R−W2)⋅cosθyleft=(R−W2)⋅sinθ \begin{cases} x_{left} = -R + (R-\tfrac{W}{2})\cdot\cos\theta \\ y_{left} = (R-\tfrac{W}{2})\cdot\sin\theta \end{cases} {xleft=−R+(R−2W)⋅cosθyleft=(R−2W)⋅sinθ
右轮(外侧轮,转弯半径R+W/2R+W/2R+W/2):
{xright=−R+(R+W2)⋅cosθyright=(R+W2)⋅sinθ \begin{cases} x_{right} = -R + (R+\tfrac{W}{2})\cdot\cos\theta \\ y_{right} = (R+\tfrac{W}{2})\cdot\sin\theta \end{cases} {xright=−R+(R+2W)⋅cosθyright=(R+2W)⋅sinθ
-
右转(δ<0\delta<0δ<0,ICR圆心O(R,0)O(R,0)O(R,0))
后轴中心轨迹:
{xcenter=R−R⋅cosθycenter=R⋅sinθ \begin{cases} x_{center} = R - R\cdot\cos\theta \\ y_{center} = R\cdot\sin\theta \end{cases} {xcenter=R−R⋅cosθycenter=R⋅sinθ
左轮(外侧轮,转弯半径R+W/2R+W/2R+W/2)、右轮(内侧轮,转弯半径R−W/2R-W/2R−W/2)同步切换半径。
2.4.3 直行特殊分支处理
当∣δ∣<10−4|\delta|<10^{-4}∣δ∣<10−4(近似0转角),RRR无穷大,轨迹简化为垂直直线:
左轮固定x=−W/2x=-W/2x=−W/2,右轮固定x=W/2x=W/2x=W/2,仅Y轴随行驶距离递增,规避tan0\tan0tan0除零报错。
三、轨迹绘制完整流水线(算法分步拆解)
步骤1:CAN信号输入与参数归一化
- 读取方向盘转角电压信号,标定换算前轮等效转角δ\deltaδ;
- 限制转角区间−max_angle,max_angle-max\\_angle,max\\_angle−max_angle,max_angle,过滤方向盘过度转动异常值;
- 载入车辆标定固有参数:轴距、轮距、最大轨迹距离(车前8米)、采样步长(0.05m,步长越小曲线越平滑)。
步骤2:世界坐标轨迹点批量生成
循环累加行驶弧长sss,逐点计算左轮、右轮、车身中心三组轨迹世界坐标(x,y)(x,y)(x,y),输出离散点列表。
行业优化点:步长统一0.05m,兼顾顺滑度与计算量;最大轨迹距离8m匹配摄像头有效视野,过滤远处无效点。
步骤3:世界坐标 → 图像像素坐标转换
地面米制坐标无法直接绘制屏幕,需要缩放+坐标平移映射:
{px=img_w2+x⋅scalepy=img_h−bottom_margin−y⋅scale \begin{cases} px = \frac{img\_w}{2} + x\cdot scale \\ py = img\_h - bottom\_margin - y\cdot scale \end{cases} {px=2img_w+x⋅scalepy=img_h−bottom_margin−y⋅scale
- scalescalescale:比例尺(像素/米),控制画面放大缩小;
- bottom_marginbottom\_marginbottom_margin:车尾底部留白,避免车身矩形贴画布底边;
- 图像像素坐标系:画布左上角为原点,Y轴向下,因此地面+Y(车头)映射为图像-py。
步骤4:图像抗锯齿线条渲染
- 三组轨迹线分层绘制:中心灰色参考线、左轮绿色线、右轮红色安全边界线;
- 每隔固定采样点绘制横向连接线,模拟AVM距离标尺;
- 绘制车身矩形框、后轮起点标记圆,直观区分车辆当前位置;
- 启用
LINE_AA抗锯齿,消除车载屏幕线条锯齿感。
步骤5:嵌入式后置处理(实车必备,仿真代码简化省略)
- 鱼眼畸变矫正:基于Brown-Conrady模型修正摄像头广角拉伸失真;
- IPM逆透视变换:将地面鸟瞰世界点映射到后视/环视摄像头原始图像;
- 转角低通滤波:平滑方向盘抖动,防止轨迹线高频闪烁;
- GPU纹理叠加:轨迹预生成纹理,与摄像头画面混合输出,降低CPU占用。
四、车载行业三大主流轨迹实现算法对比
4.1 方案一:实时阿克曼几何计算(本文仿真代码方案,主流中高端AVM)
原理
上电后根据实时方向盘转角,通过三角函数实时计算每帧轨迹点,无预存数据。
优势
- 适配任意车型轴距、轮距标定,参数可动态配置;
- 轨迹精度最高,左右转向无失真,包络线完全匹配真实车轮路径;
- 支持自定义轨迹长度、采样精度,适配不同摄像头视野。
劣势
每帧需要sin/cos浮点运算,低端8位MCU算力不足会产生延迟;
适用场景
10万以上车型360全景环视、安卓/QNX车载HMI视觉SOC。
4.2 方案二:转角分段查表法(低成本倒车影像专用)
原理
出厂前将前轮转角离散分段(如每2°一档),预计算对应轨迹点存储Flash表格;运行时读取当前转角,查表直接输出坐标,跳过实时三角函数计算。
优势
几乎无实时浮点运算,单片机即可驱动,成本极低;
劣势
转角档位离散,方向盘小幅转动时轨迹跳跃;车型标定参数修改需要重新烧录表格;
适用场景
低端燃油车单路后视倒车影像、低成本后装导航。
4.3 方案三:高阶平滑曲线规划(自动驾驶APA自动泊车、高速领航轨迹)
阿克曼圆弧仅适用于低速恒定转角场景,自动泊车、换道需要连续变曲率平滑轨迹,行业采用两类曲线:
- 五次多项式曲线
约束起点/终点位置、速度、加速度连续,换道路径无顿挫,用于高速局部路径规划; - 回旋曲线(Clothoid)/三阶贝塞尔曲线
曲率线性平滑过渡,衔接直行与转弯圆弧,APA泊车多段拼接轨迹核心算法。
对比阿克曼圆弧
阿克曼:单一固定曲率圆弧,仅适配恒定方向盘角度 低速倒车;
多项式/贝塞尔:可变曲率,适配方向盘持续转动、动态避障场景,计算复杂度大幅提升。
| 算法方案 | 计算开销 | 轨迹平滑度 | 适用场景 |
|---|---|---|---|
| 实时阿克曼几何 | 中(浮点三角函数) | 高(均匀采样) | AVM动态倒车轨迹 |
| 转角查表法 | 极低(数组读取) | 一般(档位跳变) | 低端倒车影像 |
| 五次多项式/贝塞尔 | 高(方程组求解) | 极高(连续曲率) | 自动泊车、自动驾驶规划 |
五、完整仿真代码逐行解析(可直接运行出图)
python
import cv2
import numpy as np
import math
import os
# ===================== 车辆标定固有参数(实车标定修改此处) =====================
wheel_base = 2.7 # 轴距 m
track_width = 1.8 # 轮距 m
max_angle = math.radians(35) # 前轮最大转角35度
def calc_wheel_trajs(steer_angle, step=0.05, max_dist=8.0):
"""
核心函数:基于阿克曼模型生成左轮、右轮、车身中心三组世界轨迹点
:param steer_angle: 前轮等效转角,rad,正数左转、负数右转
:param step: 轨迹采样步长,单位m,越小曲线越平滑
:param max_dist: 轨迹向前最大绘制距离,单位m
:return: left_pts左轮, right_pts右轮, center_pts车身中心 世界坐标列表
"""
half_track = track_width / 2.0
left_pts = []
right_pts = []
center_pts = []
# 分支1:直行,转角接近0,规避tan(0)除零错误
if abs(steer_angle) < 1e-4:
s = 0.0
while s <= max_dist:
left_pts.append((-half_track, s))
right_pts.append((half_track, s))
center_pts.append((0.0, s))
s += step
return left_pts, right_pts, center_pts
# 分支2:转弯行驶,计算转弯半径
turn_left = steer_angle > 0
radius = abs(wheel_base / math.tan(steer_angle))
s = 0.0
while s <= max_dist:
theta = s / radius # 弧长换算圆心角 核心公式
if turn_left:
# 左转:圆心(-R,0),左轮半径R-half_track,右轮R+half_track
cx = -radius + radius * math.cos(theta)
cy = radius * math.sin(theta)
lx = -radius + (radius - half_track) * math.cos(theta)
ly = (radius - half_track) * math.sin(theta)
rx = -radius + (radius + half_track) * math.cos(theta)
ry = (radius + half_track) * math.sin(theta)
else:
# 右转:圆心(R,0),左轮半径R+half_track,右轮R-half_track
cx = radius - radius * math.cos(theta)
cy = radius * math.sin(theta)
lx = radius - (radius + half_track) * math.cos(theta)
ly = (radius + half_track) * math.sin(theta)
rx = radius - (radius - half_track) * math.cos(theta)
ry = (radius - half_track) * math.sin(theta)
center_pts.append((cx, cy))
left_pts.append((lx, ly))
right_pts.append((rx, ry))
s += step
return left_pts, right_pts, center_pts
def world_to_pixel(pt, img_w, img_h, scale, bottom_margin):
""" 世界米坐标 转换 画布像素坐标 """
x, y = pt
px = int(img_w / 2 + x * scale)
py = int(img_h - bottom_margin - y * scale)
return [px, py]
def draw_polyline(img, pts, color, thickness=2):
""" 绘制抗锯齿轨迹折线 """
if len(pts) > 1:
cv2.polylines(img, [np.array(pts, dtype=np.int32)], False, color, thickness, cv2.LINE_AA)
def draw_car_trajectory():
# 画布配置
img_w, img_h = 800, 600
img = np.zeros((img_h, img_w, 3), dtype=np.uint8)
scale = 55 # 比例尺:1米=55像素
bottom_margin = 60 # 车尾底部留白像素
steer = math.radians(20) # 测试:左转20度,负数改为右转
# 1.生成世界轨迹点
left_pts, right_pts, center_pts = calc_wheel_trajs(steer)
# 2.批量转换像素坐标
left_pix = [world_to_pixel(p, img_w, img_h, scale, bottom_margin) for p in left_pts]
right_pix = [world_to_pixel(p, img_w, img_h, scale, bottom_margin) for p in right_pts]
center_pix = [world_to_pixel(p, img_w, img_h, scale, bottom_margin) for p in center_pts]
# 3.绘制三组轨迹线 BGR颜色通道
draw_polyline(img, center_pix, (180, 180, 180), 1) # 车身中心 灰色细线
draw_polyline(img, left_pix, (0, 255, 0), 2) # 左轮 绿色
draw_polyline(img, right_pix, (0, 0, 255), 2) # 右轮外侧安全边界 红色
# 绘制横向距离标尺连接线
for i in range(0, min(len(left_pix), len(right_pix)), 20):
cv2.line(img, tuple(left_pix[i]), tuple(right_pix[i]), (80, 80, 80), 1, cv2.LINE_AA)
# 绘制车身矩形框
car_w = int(track_width * scale)
car_l = int(4.5 * scale) # 车长4.5米
rear_cx, rear_cy = img_w // 2, img_h - bottom_margin
cv2.rectangle(img, (rear_cx - car_w // 2, rear_cy - car_l),
(rear_cx + car_w // 2, rear_cy), (255, 255, 255), 2)
cv2.line(img, (rear_cx, rear_cy), (rear_cx, rear_cy - car_l), (255, 255, 0), 1, cv2.LINE_AA)
# 后轮起点标记圆点
cv2.circle(img, tuple(left_pix[0]), 5, (0, 255, 0), -1, cv2.LINE_AA)
cv2.circle(img, tuple(right_pix[0]), 5, (0, 0, 255), -1, cv2.LINE_AA)
# 保存图片到脚本同级目录
output_file = os.path.join(os.path.dirname(__file__), "test_car_trajectory.png")
cv2.imwrite(output_file, img)
print(f"轨迹仿真图已保存:{output_file}")
# 环境变量DISPLAY_IMAGE=1时弹窗预览图片
if os.environ.get("DISPLAY_IMAGE", "0") == "1":
cv2.imshow("Car Trajectory Simulation", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == "__main__":
draw_car_trajectory()
代码运行效果说明

六、实车工程常见问题与优化方案
6.1 轨迹左右不对称、偏移失真
- 根因:轴距/轮距标定参数错误;转角换算系数偏移;左右转向半径公式混用;
- 优化:实车场地标定,测量真实轴距、轮距,单独校验左转/右转分支坐标方程。
6.2 轨迹线条持续闪烁抖动
- 根因:CAN方向盘转角传感器噪声,每帧转角剧烈跳变;
- 优化:一阶低通滤波平滑转角输入,限制单帧转角最大变化量。
6.3 嵌入式设备帧率低、画面卡顿
- 预计算三角函数表,替代实时sin/cos运算;
- 减少采样点步长,降低每帧绘制点数量;
- GPU离线生成轨迹纹理,图层叠加渲染,CPU仅传输坐标数据。
6.4 摄像头画面轨迹错位,不贴合地面
- 根因:缺少鱼眼畸变矫正、未做IPM逆透视变换;
- 优化:先矫正摄像头畸变,再将世界轨迹点通过透视矩阵映射到原始图像像素。
七、总结
动态倒车轨迹线核心依托阿克曼转向几何模型,通过弧长极坐标法均匀生成车轮行驶离散坐标,经坐标缩放映射、抗锯齿渲染输出辅助线条。
行业根据硬件算力、功能定位分为查表法、实时几何计算、高阶平滑曲线三类实现方案:低端后视影像采用查表法,360全景AVM使用实时阿克曼计算,自动泊车与自动驾驶采用五次多项式、贝塞尔变曲率曲线。
