{ "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 }