313 lines
8.6 KiB
Plaintext
313 lines
8.6 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 59,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%matplotlib widget"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 60,
|
|
"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": 61,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stderr",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"<>:5: SyntaxWarning: invalid escape sequence '\\g'\n",
|
|
"<>:5: SyntaxWarning: invalid escape sequence '\\g'\n",
|
|
"/tmp/ipykernel_100064/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": 62,
|
|
"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",
|
|
" _Fz=float(1.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: _Fz})\n",
|
|
"\n",
|
|
" return plot(result, (x, -100, 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": 63,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pyperclip\n",
|
|
"\n",
|
|
"def copy_to_clipboard(text):\n",
|
|
" pyperclip.copy(text)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 64,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "dc81af6a67754c5d8127cc89eb70368b",
|
|
"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": "e09f497a55324a8ba3e35f5624741bce",
|
|
"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",
|
|
" -1.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[:-2])))\n",
|
|
"\n",
|
|
"display(w)\n",
|
|
"display(copy_long_btn)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 65,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "60b3a140f56547828b45f3038c9c039c",
|
|
"version_major": 2,
|
|
"version_minor": 0
|
|
},
|
|
"text/plain": [
|
|
"interactive(children=(FloatSlider(value=0.0, description='a0', max=1.0), FloatSlider(value=0.0, description='a…"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"application/vnd.jupyter.widget-view+json": {
|
|
"model_id": "01b9a4caf90c43caadf998126c9f5c51",
|
|
"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_lat_btn = widgets.Button(description=\"Copy Params\")\n",
|
|
"copy_lat_btn.on_click(lambda _: copy_to_clipboard(',\\n'.join(str(p.value) for p in widget_lat.children[:-2])))\n",
|
|
"\n",
|
|
"display(widget_lat)\n",
|
|
"display(copy_lat_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
|
|
}
|