给自动驾驶新手:用Python从零实现运动学自行车模型(附完整代码)

自动驾驶技术的核心在于对车辆运动的精确建模。运动学自行车模型(Kinematic Bicycle Model)作为入门级建模方法,通过简化车辆结构为两轮自行车,帮助初学者理解基础原理。本文将带您从零开始,用Python完整实现这一模型,涵盖后轴、前轴及质心三种参考点的代码实现,最终生成可视化轨迹。

1. 环境准备与基础概念

在开始编码前,需要确保Python环境已安装以下库:

pip install numpy matplotlib scipy

运动学自行车模型 的核心假设包括:

  • 车辆简化为前后两轮结构(类似自行车)
  • 无横向滑移(Nonholonomic约束)
  • 转向角变化瞬时完成

模型的关键参数定义:

符号 含义 典型值
L 轴距(前后轮距离) 2.5m
δ 前轮转向角 [-0.5,0.5]rad
v 车速 5m/s

注意:实际车辆转向角存在物理限制,仿真时需添加约束条件

2. 后轴参考点模型实现

后轴作为参考点时,车辆状态可表示为:

state = [x, y, theta]  # (x坐标,y坐标,航向角)

根据几何关系,推导出微分方程:

dx/dt = v * cos(θ)
dy/dt = v * sin(θ)
dθ/dt = v * tan(δ) / L

Python实现代码:

def kinematic_model_rear(state, t, v, delta, L):
    theta = state[2]
    dxdt = v * np.cos(theta)
    dydt = v * np.sin(theta)
    dthetadt = v * np.tan(delta) / L
    return [dxdt, dydt, dthetadt]

可视化示例:

# 参数设置
L = 2.5
v = 5.0
delta = np.pi/6  # 30度转向

# 数值积分求解
from scipy.integrate import odeint
t = np.linspace(0, 10, 100)
states = odeint(kinematic_model_rear, [0,0,0], t, args=(v,delta,L))

# 绘制轨迹
plt.plot(states[:,0], states[:,1])
plt.axis('equal')
plt.title('后轴参考点轨迹')

3. 前轴与质心参考点扩展

3.1 前轴参考点模型

前轴作为参考点时,速度方向为δ+θ:

def kinematic_model_front(state, t, v, delta, L):
    theta = state[2]
    dxdt = v * np.cos(theta + delta)
    dydt = v * np.sin(theta + delta)
    dthetadt = v * np.tan(delta) / L
    return [dxdt, dydt, dthetadt]

3.2 质心参考点模型

引入侧滑角β的概念:

def kinematic_model_cg(state, t, v, delta, L, lr):
    theta = state[2]
    beta = np.arctan(lr * np.tan(delta) / L)
    dxdt = v * np.cos(theta + beta)
    dydt = v * np.sin(theta + beta)
    dthetadt = v * np.tan(delta) * np.cos(beta) / L
    return [dxdt, dydt, dthetadt]

三种模型的轨迹对比:

# 相同参数下仿真
states_rear = odeint(kinematic_model_rear, [0,0,0], t, args=(v,delta,L))
states_front = odeint(kinematic_model_front, [0,0,0], t, args=(v,delta,L))
states_cg = odeint(kinematic_model_cg, [0,0,0], t, args=(v,delta,L,1.5))

plt.plot(states_rear[:,0], states_rear[:,1], label='后轴')
plt.plot(states_front[:,0], states_front[:,1], label='前轴')
plt.plot(states_cg[:,0], states_cg[:,1], label='质心')
plt.legend()

4. 完整仿真系统实现

构建可交互的仿真系统:

class BicycleSimulator:
    def __init__(self, L=2.5, lr=1.2):
        self.L = L  # 轴距
        self.lr = lr  # 后轴到质心距离
        
    def simulate(self, v, delta, duration=10, ref_point='rear'):
        t = np.linspace(0, duration, 100)
        if ref_point == 'rear':
            states = odeint(kinematic_model_rear, [0,0,0], t, args=(v,delta,self.L))
        elif ref_point == 'front':
            states = odeint(kinematic_model_front, [0,0,0], t, args=(v,delta,self.L))
        else:
            states = odeint(kinematic_model_cg, [0,0,0], t, args=(v,delta,self.L,self.lr))
        return states

典型应用场景测试:

sim = BicycleSimulator()

# 不同转向角测试
for delta in np.linspace(-0.5, 0.5, 5):
    states = sim.simulate(v=3, delta=delta, ref_point='cg')
    plt.plot(states[:,0], states[:,1], label=f'delta={delta:.2f}')
plt.legend()
plt.title('不同转向角下的质心轨迹')

5. 进阶应用与问题排查

5.1 转向角速率限制

实际车辆转向存在机械限制,需添加约束:

def constrained_delta(delta_cmd, delta_prev, max_rate=0.1):
    delta_change = delta_cmd - delta_prev
    if abs(delta_change) > max_rate:
        return delta_prev + np.sign(delta_change)*max_rate
    return delta_cmd

5.2 常见问题解决方案

问题现象 可能原因 解决方法
轨迹突然跳变 转向角突变 添加速率限制
数值不稳定 积分步长过大 减小时间步长
轨迹不符合预期 参考点选择错误 检查模型公式

提示:调试时可先固定转向角,验证直线运动是否正确

6. 模型扩展与性能优化

6.1 动态参数调整

def adaptive_model(state, t, v_func, delta_func, L):
    v = v_func(t)  # 速度随时间变化
    delta = delta_func(t)  # 转向角随时间变化
    return kinematic_model_rear(state, t, v, delta, L)

6.2 实时可视化技巧

from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
line, = ax.plot([], [], 'b-')

def init():
    ax.set_xlim(-10, 50)
    ax.set_ylim(-10, 10)
    return line,

def animate(i):
    states = sim.simulate(v=5, delta=0.2, duration=i/10)
    line.set_data(states[:,0], states[:,1])
    return line,

ani = FuncAnimation(fig, animate, frames=100, init_func=init, blit=True)

实现过程中发现,当转向角超过物理极限时,质心模型的侧滑角计算会出现数值不稳定。解决方法是在arctan计算前添加范围限制:

beta = np.arctan(np.clip(lr * np.tan(delta) / L, -1e5, 1e5))

更多推荐