305 lines
8.5 KiB
Plaintext
305 lines
8.5 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%matplotlib widget"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from sympy import Symbol, sin, atan, exp, solve, diff, simplify,Eq,sign\n",
|
|
"from sympy.plotting import plot, plot3d\n",
|
|
"\n",
|
|
"\n",
|
|
"from ipywidgets import interact, interactive, fixed, interact_manual\n",
|
|
"from IPython.display import display\n",
|
|
"import ipywidgets as widgets\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"<>:5: SyntaxWarning: invalid escape sequence '\\g'\n",
|
|
"<>:5: SyntaxWarning: invalid escape sequence '\\g'\n",
|
|
"/tmp/ipykernel_97985/2069913084.py:5: SyntaxWarning: invalid escape sequence '\\g'\n",
|
|
" camber_angle = Symbol('\\gamma')\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"a = [Symbol(f'a_{i}', real=True) for i in range(18)]\n",
|
|
"b = [Symbol(f'b_{i}', real=True) for i in range(14)]\n",
|
|
"Fz = Symbol('F_z', positive=True, real=True)\n",
|
|
"x = Symbol('x', real=True)\n",
|
|
"camber_angle = Symbol('\\gamma')\n",
|
|
"\n",
|
|
"def pacejka94_longitudinal():\n",
|
|
"\tFz_sq = Fz * Fz\n",
|
|
"\n",
|
|
"\tC = b[0]\n",
|
|
"\tD = (b[1] * Fz + b[2]) * Fz\n",
|
|
"\tBCD = (b[3] * Fz_sq + b[4] * Fz) * exp(-b[5] * Fz)\n",
|
|
"\tB = BCD / (C * D)\n",
|
|
"\tH = b[9] * Fz + b[10]\n",
|
|
"\tE = (b[6] * Fz_sq + b[7] * Fz + b[8]) * (1.0 - b[13] * sign(x + H))\n",
|
|
"\tV = b[11] * Fz + b[12]\n",
|
|
"\tBx1 = B * (x + H)\n",
|
|
"\n",
|
|
"\tF = D * sin(C * atan(Bx1 - E * (Bx1 - atan(Bx1)))) + V\n",
|
|
"\n",
|
|
"\treturn F / (Fz * 1000)\n",
|
|
"\n",
|
|
"def pacejka94_lateral():\n",
|
|
"\tcamber_angle_sq = camber_angle * camber_angle\n",
|
|
"\n",
|
|
"\tC = a[0]\n",
|
|
"\tD = Fz * (a[1] * Fz + a[2]) * (1.0 - a[15] * camber_angle_sq)\n",
|
|
"\tBCD = a[3] * sin(atan(Fz / a[4]) * 2.0) * (1.0 - a[5] * abs(camber_angle))\n",
|
|
"\tB = BCD / (C * D)\n",
|
|
"\tH = a[8] * Fz + a[9] + a[10] * camber_angle\n",
|
|
"\tE = (a[6] * Fz + a[7]) * (1.0 - (a[16] * camber_angle + a[17]) * sign(x + H))\n",
|
|
"\tV = a[11] * Fz + a[12] + (a[13] * Fz + a[14]) * camber_angle * Fz\n",
|
|
"\tBx1 = B * (x + H)\n",
|
|
"\n",
|
|
"\tF = D * sin(C * atan(Bx1 - E * (Bx1 - atan(Bx1)))) + V\n",
|
|
"\treturn F / (Fz * 1000)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# slip_angle_formula = pacejka96().subs({sym: val for sym, val in zip(b, slip_angle_b)})\n",
|
|
"# slip_angle_formula2 = pacejka96().subs({sym: val for sym, val in zip(b, slip_angle_b2)})\n",
|
|
"# slip_ratio_formula = pacejka96().subs({sym: val for sym, val in zip(b, slip_ratio_b)})\n",
|
|
"# \n",
|
|
"# plot(abs((slip_angle_formula / (Fz * 1000)).subs({Fz: 2})), abs((slip_ratio_formula / (Fz * 1000)).subs({Fz: 2})), (x, 0, 30))\n",
|
|
"\n",
|
|
"def pacejka_longitudinal_interactive(\n",
|
|
" b0 = 1.5,\n",
|
|
" b1 = 0.0,\n",
|
|
" b2 = 1100.0,\n",
|
|
" b3 = 0.0,\n",
|
|
" b4 = 300.0,\n",
|
|
" b5 = 0.0,\n",
|
|
" b6 = 0.0,\n",
|
|
" b7 = 0.0,\n",
|
|
" b8 = -2.0,\n",
|
|
" b9 = 0.0,\n",
|
|
" b10 = 0.0,\n",
|
|
" b11 = 0.0,\n",
|
|
" b12 = 0.0,\n",
|
|
" b13 = 0.0,\n",
|
|
" ):\n",
|
|
" params = [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13]\n",
|
|
" result = pacejka94_longitudinal().subs({sym: val for sym, val in zip(b, params)})\n",
|
|
" result = result.subs({Fz: 1})\n",
|
|
"\n",
|
|
" return plot(result, (x, 0, 100))\n",
|
|
"\n",
|
|
"def pacejka_lateral_interactive(\n",
|
|
" a0 = float(0.0),\n",
|
|
" a1 = float(0.0),\n",
|
|
" a2 = float(0.0),\n",
|
|
" a3 = float(0.0),\n",
|
|
" a4 = float(0.0),\n",
|
|
" a5 = float(0.0),\n",
|
|
" a6 = float(0.0),\n",
|
|
" a7 = float(0.0),\n",
|
|
" a8 = float(0.0),\n",
|
|
" a9 = float(0.0),\n",
|
|
" a10 = float(0.0),\n",
|
|
" a11 = float(0.0),\n",
|
|
" a12 = float(0.0),\n",
|
|
" a13 = float(0.0),\n",
|
|
" a14 = float(0.0),\n",
|
|
" a15 = float(0.0),\n",
|
|
" a16 = float(0.0),\n",
|
|
" a17 = float(0.0),\n",
|
|
" _camber_angle=float(0.0)\n",
|
|
" ):\n",
|
|
" params = [a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17]\n",
|
|
" result = pacejka94_lateral().subs({sym: val for sym, val in zip(a, params)})\n",
|
|
" result = result.subs({Fz: 1, camber_angle: _camber_angle})\n",
|
|
"\n",
|
|
" return plot(result, (x, -90, 90))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pyperclip\n",
|
|
"\n",
|
|
"def copy_to_clipboard(text):\n",
|
|
" pyperclip.copy(text)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "ad99275593cc4cc0a0d9bbd2418231cf",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"interactive(children=(FloatSlider(value=1.5, description='b0', max=4.5, min=-1.5), FloatSlider(value=0.0, desc…"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "57e3277511e346aabc5d38e222bc8eee",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"Button(description='Copy Params', style=ButtonStyle())"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"long_params = [\n",
|
|
" 1.5,\n",
|
|
" 0.0,\n",
|
|
" 1100.0,\n",
|
|
" 0.0,\n",
|
|
" 300.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0,\n",
|
|
" -2.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0,\n",
|
|
" 0.0\n",
|
|
"]\n",
|
|
"\n",
|
|
"w = interactive(pacejka_longitudinal_interactive, kwargs={f'b{i}': long_params[i] for i in range(len(long_params))})\n",
|
|
"\n",
|
|
"copy_long_btn = widgets.Button(description=\"Copy Params\")\n",
|
|
"copy_long_btn.on_click(lambda _: copy_to_clipboard(',\\n'.join(str(p.value) for p in w.children[:-1])))\n",
|
|
"\n",
|
|
"display(w)\n",
|
|
"display(copy_long_btn)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "ad99275593cc4cc0a0d9bbd2418231cf",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"interactive(children=(FloatSlider(value=1.5, description='b0', max=4.5, min=-1.5), FloatSlider(value=0.0, desc…"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "3c5b82c12f154727a32aed50b1f8fc59",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"Button(description='Copy Params', style=ButtonStyle())"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"lat_params = [\n",
|
|
"\t1.4,\n",
|
|
"\t0.0,\n",
|
|
"\t1100.0,\n",
|
|
"\t1100.0,\n",
|
|
"\t10.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t-2.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"\t0.0,\n",
|
|
"]\n",
|
|
"\n",
|
|
"widget_lat = interactive(pacejka_lateral_interactive, kwargs={f'a{i}': lat_params[i] for i in range(len(lat_params))})\n",
|
|
"\n",
|
|
"copy_long_btn = widgets.Button(description=\"Copy Params\")\n",
|
|
"copy_long_btn.on_click(lambda _: copy_to_clipboard(',\\n'.join(str(p.value) for p in w.children[:-2])))\n",
|
|
"\n",
|
|
"display(w)\n",
|
|
"display(copy_long_btn)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.13.2"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|