摩托车圈速模拟器g-g图绘制:Python求根代码正确性验证问询
摩托车g-g图绘制:求根代码验证与曲线补全解决方案
问题概述
我正在为摩托车圈速模拟器绘制g-g图(x轴为横向加速度ay,y轴为纵向加速度ax)。已知除ax外的所有参数,参考视频编写了求根代码,但绘图结果不符合预期。当前完整代码仅能展示ax正负区间的分段曲线,需要补全正负部分的连接,同时验证求根代码的正确性。
求根代码问题分析
原求根代码存在两个核心问题:
- 参数传递逻辑错误:函数
fxn1定义中ax是待求解变量,但调用时将ax数组作为第一个参数传入,同时固定ay为单一值,与g-g图需要遍历不同ay求解对应ax的逻辑完全相反。 - 函数用途误解:当前代码是绘制
fxn1随ax变化的曲线,而非求解fxn1(ax)=0的根——这才是获取每个ay对应极限ax的正确方式。
曲线补全问题分析
原完整代码仅分开计算了加速段(Wheelie_Min)和减速段(Deceleration_Max),但未整合轮胎摩擦力椭圆约束与抬头/翘尾的物理边界,导致曲线无法完整闭合。需要对每个ay值,同时计算可行的最大加速ax和最小减速ax,并确保所有约束(功率、抬头、翘尾、轮胎摩擦力)都被应用。
修正后的完整实现
以下代码整合了求根逻辑与所有物理约束,生成完整的g-g曲线:
import numpy as np import matplotlib.pyplot as plt from scipy.optimize import root_scalar # 物理参数 g = 9.81 # 重力加速度 pa = 1.2 # 空气密度 m = 250 # 摩托车质量 h = 0.69 # 质心高度 ha = 0.69 # 压力中心高度 w = 1.5 # 轴距 b = 0.73 # 质心到前轴的纵向距离 CdA = 0.2 # 风阻系数×迎风面积 PMax = 180000 # 最大功率 ux = 1.2 # 纵向摩擦系数 uy = 1.44 # 横向摩擦系数 V = 20 # 基准速度 # 预计算参数 Fd = 0.5 * pa * CdA * V**2 # 空气阻力 Ap = ((PMax / (m * V)) - (Fd / m)) / g # 无横向加速度时的最大加速(功率限制) # 定义求根函数:对于给定ay,求解满足轮胎摩擦力约束的ax def fxn1(ax, ay): term1 = ((w * (m*ax + Fd) * np.sqrt(ay**2 + g**2)) / (g * ((w - b)*m*np.sqrt(ay**2 + g**2) + m*ax*h + Fd*ha))) ** 2 / ux**2 term2 = (ay / g)**2 / uy**2 return term1 + term2 - 1 # 生成ay的遍历范围 yw = np.linspace(-uy, uy, 200) # 覆盖横向加速度的正负区间 # 初始化加速段和减速段的ax数组 ax_accel = np.zeros_like(yw) ax_decel = np.zeros_like(yw) for i, ay in enumerate(yw): # 求解加速状态下的ax(正ax) try: sol_accel = root_scalar(fxn1, args=(ay,), method='brentq', bracket=[0, Ap]) ax_accel[i] = sol_accel.root except: # 当超出抬头约束时,使用抬头极限值 Aw = ((b * np.sqrt((ay*g)**2 + g**2)) / h - (Fd*ha)/(m*h)) / g ax_accel[i] = min(Ap, Aw) # 求解减速状态下的ax(负ax) try: sol_decel = root_scalar(fxn1, args=(ay,), method='brentq', bracket=[-5, 0]) ax_decel[i] = sol_decel.root except: # 当超出翘尾约束时,使用翘尾极限值 As = (((w - b) * np.sqrt((ay*g)**2 + g**2)) / h - (Fd*ha)/(m*h)) / (-g) # 同时考虑轮胎摩擦力约束的减速极限 Ad = (-g * ux * np.sqrt(1 - (ay/g)**2 / uy**2) - Fd/m) / g ax_decel[i] = max(As, Ad) # 整合抬头和翘尾约束,修正加速/减速段的极限值 Aw = ((b * np.sqrt((yw*g)**2 + g**2)) / h - (Fd*ha)/(m*h)) / g ax_accel = np.minimum(ax_accel, Aw, Ap) As = (((w - b) * np.sqrt((yw*g)**2 + g**2)) / h - (Fd*ha)/(m*h)) / (-g) Ad = (-g * ux * np.sqrt(1 - (yw/g)**2 / uy**2) - Fd/m) / g ax_decel = np.maximum(ax_decel, As, Ad) # 绘制完整的g-g图 plt.figure(dpi=120) plt.plot(yw, ax_accel, 'r', label='极限加速') plt.plot(yw, ax_decel, 'r', label='极限减速') plt.fill_between(yw, ax_decel, ax_accel, color='red', alpha=0.1) plt.xlabel('横向加速度 ay (g)') plt.ylabel('纵向加速度 ax (g)') plt.title('摩托车g-g图 (基准速度20m/s)') plt.grid(True) plt.axis('equal') plt.legend() plt.show()
代码说明
- 求根逻辑修正:使用
scipy.optimize.root_scalar对每个ay值求解fxn1(ax)=0的根,得到满足轮胎摩擦力椭圆约束的极限ax。 - 约束整合:对每个
ay,同时计算功率限制、抬头限制、翘尾限制和轮胎摩擦力限制,取最严格的约束作为最终极限值。 - 曲线补全:遍历正负
ay区间,分别计算加速和减速段的ax值,最终绘制完整的闭合曲线,并填充可行区域。
内容的提问来源于stack exchange,提问作者Karl Burnett
相关产品推荐
相关产品推荐

