用Python从零实现一个2自由度车辆动力学模型(附完整代码)

张开发
2026/4/4 10:26:54 15 分钟阅读
用Python从零实现一个2自由度车辆动力学模型(附完整代码)
用Python从零构建二自由度车辆动力学模型从理论到代码实战在自动驾驶和车辆控制领域理解车辆动力学是开发可靠算法的基石。二自由度模型作为最基础的动力学表达舍弃了部分复杂性却保留了横向运动和横摆运动这两个对操控性影响最大的核心维度。本文将带您从零推导方程并用Python实现一个完整的仿真模型最后通过一个简单的轨迹跟踪示例验证模型的有效性。1. 模型基础与假设条件任何数学模型都是对现实的简化二自由度车辆模型也不例外。我们首先需要明确模型的边界和适用条件平面运动假设车辆仅在二维平面内运动忽略垂直方向的跳动和侧倾线性轮胎特性轮胎侧向力与侧偏角呈线性关系适用于常规驾驶工况通常侧向加速度小于0.4g恒定纵向速度忽略加速/制动对横向动力学的影响vx视为常数刚性车身不考虑悬架变形和车身柔性# 模型基础参数类 class VehicleParameters: def __init__(self): self.m 1727 # 质量(kg) self.Iz 1300 # 绕z轴转动惯量(kg·m²) self.lf 1.2 # 前轴到质心距离(m) self.lr 1.6 # 后轴到质心距离(m) self.Caf 80000 # 前轮总侧偏刚度(N/rad) self.Car 80000 # 后轮总侧偏刚度(N/rad)这些参数对应一辆普通乘用车您可以根据实际车辆规格调整。值得注意的是前后轮的侧偏刚度通常会有所不同这与车辆的驱动方式和重量分布有关。2. 动力学方程推导2.1 坐标系定义我们采用两种坐标系来描述车辆运动全局坐标系(X,Y)固定于地面用于记录车辆的绝对位置车身坐标系(x,y)固定于车辆质心x轴指向车辆前进方向两坐标系间的转换关系由横摆角ψ决定这是后续运动学方程推导的基础。2.2 横向动力学方程根据牛顿第二定律横向运动满足ma_y ΣF_y其中a_y包含两项横向加速度的惯性分量d²y/dt²向心加速度分量v_x·dψ/dt轮胎侧向力采用线性模型前轮侧向力F_yf 2C_αf·(δ - θ_vf)后轮侧向力F_yr 2C_αr·(-θ_vr)def calculate_lateral_forces(v_y, psi_dot, delta, v_x, params): 计算轮胎侧向力 参数 v_y: 横向速度 psi_dot: 横摆角速度 delta: 前轮转向角 v_x: 纵向速度 params: 车辆参数对象 返回 F_yf, F_yr: 前后轮侧向力 theta_vf (v_y params.lf * psi_dot) / v_x theta_vr (v_y - params.lr * psi_dot) / v_x F_yf params.Caf * (delta - theta_vf) F_yr -params.Car * theta_vr return F_yf, F_yr2.3 横摆动力学方程根据转动定律绕z轴的力矩平衡方程为I_z·ψ¨ l_f·F_yf - l_r·F_yr将侧向力表达式代入后可以得到关于横摆角加速度的显式方程。3. 状态空间模型实现将上述方程整理为状态空间形式便于后续的数值积分和控制设计。选择状态变量为x [y, v_y, ψ, ψ_dot]^T控制输入为前轮转角δ。状态方程可表示为x_dot A·x B·udef state_space_matrices(v_x, params): 生成状态空间矩阵 参数 v_x: 纵向速度(m/s) params: 车辆参数对象 返回 A, B: 状态矩阵和输入矩阵 # 状态矩阵A A np.zeros((4, 4)) A[0, 1] 1 A[1, 1] -(params.Caf params.Car) / (params.m * v_x) A[1, 3] -v_x - (params.Caf * params.lf - params.Car * params.lr) / (params.m * v_x) A[2, 3] 1 A[3, 1] -(params.Caf * params.lf - params.Car * params.lr) / (params.Iz * v_x) A[3, 3] -(params.Caf * params.lf**2 params.Car * params.lr**2) / (params.Iz * v_x) # 输入矩阵B B np.zeros((4, 1)) B[1, 0] params.Caf / params.m B[3, 0] params.Caf * params.lf / params.Iz return A, B4. 数值积分与仿真采用Runge-Kutta 4阶方法进行数值积分保证计算精度def runge_kutta4(f, x, u, dt): 4阶Runge-Kutta积分 参数 f: 状态方程函数 x: 当前状态 u: 控制输入 dt: 时间步长 返回 x_next: 下一时刻状态 k1 f(x, u) k2 f(x 0.5*dt*k1, u) k3 f(x 0.5*dt*k2, u) k4 f(x dt*k3, u) x_next x (dt/6) * (k1 2*k2 2*k3 k4) return x_next def vehicle_dynamics(t, x, u, v_x, params): 车辆动力学方程 参数 t: 时间(未使用) x: 状态向量 [y, v_y, psi, psi_dot] u: 控制输入 [delta] v_x: 纵向速度 params: 车辆参数 返回 x_dot: 状态导数 y, v_y, psi, psi_dot x delta u[0] F_yf, F_yr calculate_lateral_forces(v_y, psi_dot, delta, v_x, params) # 横向加速度 a_y (F_yf F_yr) / params.m - v_x * psi_dot # 横摆角加速度 psi_ddot (params.lf * F_yf - params.lr * F_yr) / params.Iz return np.array([v_y, a_y, psi_dot, psi_ddot])5. 轨迹跟踪示例为了验证模型的有效性我们实现一个简单的预瞄跟踪控制器。控制器根据车辆与目标轨迹的偏差计算所需前轮转角class PurePursuitController: def __init__(self, lookahead_dist5.0): self.ld lookahead_dist # 预瞄距离 def calculate_steering(self, x, y, psi, trajectory): 计算转向角 参数 x, y: 车辆当前位置 psi: 当前横摆角 trajectory: 目标轨迹点列表 返回 delta: 转向角(rad) # 寻找最近的轨迹点 closest_idx np.argmin(np.sum((trajectory - np.array([x, y]))**2, axis1)) # 选择预瞄点 lookahead_idx min(closest_idx 10, len(trajectory)-1) lookahead_point trajectory[lookahead_idx] # 计算横向误差 alpha np.arctan2(lookahead_point[1]-y, lookahead_point[0]-x) - psi # 纯追踪控制律 delta np.arctan2(2 * self.ld * np.sin(alpha), self.ld) return np.clip(delta, -0.5, 0.5) # 限制最大转向角仿真结果显示该控制器能够在中等速度下较好地跟踪参考轨迹验证了模型的基本正确性。实际应用中还需要考虑以下改进方向引入纵向动力学耦合考虑轮胎非线性特性增加路面坡度影响优化控制算法如MPC完整代码实现包含了可视化部分可以直观展示车辆运动轨迹和状态变化帮助理解模型行为。通过调整参数您能观察到不同车辆配置对操控特性的影响这正是动力学模型的价值所在。

更多文章