Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 56 additions & 78 deletions docs/notebooks/symbolic.ipynb
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<!-- RTB_HEADER -- generated from the notebook metadata (rtb_header) by sync_bootstrap.py, do not hand-edit -->\n",
"<table>\n",
" <tr>\n",
" <td><div align=\"left\"><font size=\"30\">Robotics Toolbox for Python</font></div></td>\n",
" <td><img src=\"figs/RobToolBox_RoundLogoB.png\" width=\"300\"></td>\n",
" </tr>\n",
"</table>\n",
"\n",
"<p></p>\n",
"<div align=\"center\" style=\"font-size: 1.5em;\">Symbolic computation</div>\n",
"<p></p>\n",
"\n",
"(c) Peter Corke 2026\n",
"\n",
"Forward kinematics and inverse dynamics of a Puma 560 robot with symbolic joint variables, and generating code from the results. The dynamics section takes a few minutes to run in full.\n",
"\n",
"> **Modernised 2026-10-19** to address API drift: this notebook was written for an earlier release of the Toolbox, and has been updated so that it runs with the current one."
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -51,7 +74,7 @@
" print(f'Running {where} using RTB v{version}')\n",
" return colab\n",
"\n",
"COLAB = await ensure_installed()\n"
"COLAB = await ensure_installed(extras=['ik'])\n"
]
},
{
Expand Down Expand Up @@ -560,7 +583,7 @@
"outputs": [],
"source": [
"g = sym.symbol('g')\n",
"puma.gravity = [0, 0, g]"
"puma.gravity = [0, 0, -g]"
]
},
{
Expand Down Expand Up @@ -596,7 +619,7 @@
"source": [
"Now we compute the inverse dynamics as a function of symbolic joint coordinates, velocities, accelerations and gravity as well as a lot of numerical kinematic and dynamic parameters.\n",
"\n",
"Note that this next step might take 10 minutes or more to execute (but the result will be impressive and worth the wait!)"
"This takes a second or so. The result is impressive: each torque is an expression with thousands of terms. Note that `gravity` is the acceleration due to gravity, so for the usual orientation of the Puma it is `[0, 0, -g]`."
]
},
{
Expand Down Expand Up @@ -629,69 +652,17 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%time z = simplify(tau[4])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%time z = simplify(tau[3])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%time z = simplify(tau[2])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%time z = simplify(tau[1])"
]
},
{
"cell_type": "code",
"execution_count": null,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"%time z = simplify(tau[0])"
"SymPy's `simplify` can reduce these expressions a lot, but it takes longer the more terms there are. It took about a second for the last joint, 15 seconds for $\\tau_3$, 50 seconds for $\\tau_4$ and several minutes for $\\tau_2$, which we will not wait for."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The result `tau` is not a NumPy array as it would be for the numeric case"
"The result `tau` is a NumPy array, as it is for the numeric case, but with `dtype=object` since each element is a SymPy expression"
]
},
{
Expand All @@ -707,7 +678,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"but it is the symbolic (SymPy) equivalent and it has the expected shape"
"and it has the expected shape"
]
},
{
Expand Down Expand Up @@ -781,7 +752,7 @@
"metadata": {},
"outputs": [],
"source": [
"m = tau[0].coeff(qdd[0]).args\n",
"m = tau_0.coeff(qdd[0]).args\n",
"m"
]
},
Expand All @@ -800,7 +771,7 @@
"metadata": {},
"outputs": [],
"source": [
"m = tau[0].coeff(qdd[1]).args\n",
"m = tau_0.coeff(qdd[1]).args\n",
"m"
]
},
Expand All @@ -819,7 +790,7 @@
"metadata": {},
"outputs": [],
"source": [
"c = tau[0].coeff(qd[0]).args\n",
"c = tau_0.coeff(qd[0]).args\n",
"c"
]
},
Expand All @@ -837,7 +808,8 @@
"metadata": {},
"outputs": [],
"source": [
"C = tau[0].coeff(qd[0]).coeff(qd[0]).args"
"C = tau_0.coeff(qd[0], 2).args\n",
"C"
]
},
{
Expand All @@ -850,11 +822,14 @@
]
},
{
"cell_type": "markdown",
"cell_type": "code",
"metadata": {},
"source": [
"c = tau[0].coeff(qd[0]).coeff(qd[1]).args"
]
"c = tau_0.coeff(qd[0]).coeff(qd[1]).args\n",
"c"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -944,7 +919,7 @@
"metadata": {},
"outputs": [],
"source": [
"signif_terms = [t for t in tau_0.args if abs(t.args[0]) > 1e-6]\n",
"signif_terms = [t for t in tau_0.args if abs(t.args[0]) > 1e-2]\n",
"signif_terms"
]
},
Expand Down Expand Up @@ -1024,11 +999,9 @@
"outputs": [],
"source": [
"subsdict = {}\n",
"sqdict = {}\n",
"for j in range(puma.n):\n",
" subsdict[qd[j]] = 0\n",
" subsdict[qdd[j]] = 0}\n",
" sqdict[]"
" subsdict[qdd[j]] = 0"
]
},
{
Expand All @@ -1037,7 +1010,7 @@
"metadata": {},
"outputs": [],
"source": [
"tau_g = tau.subs(subsdict)\n",
"tau_g = [t.subs(subsdict) for t in tau]\n",
"tau_g"
]
},
Expand Down Expand Up @@ -1086,13 +1059,6 @@
"source": [
"t1.expand().subs(sqdict)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down Expand Up @@ -1154,6 +1120,18 @@
"_Feature"
],
"window_display": false
},
"rtb_header": {
"title": "Symbolic computation",
"paragraphs": [
"Forward kinematics and inverse dynamics of a Puma 560 robot with symbolic joint variables, and generating code from the results. The dynamics section takes a few minutes to run in full."
],
"modernised": "2026-10-19"
},
"rtb_bootstrap": {
"extras": [
"ik"
]
}
},
"nbformat": 4,
Expand Down
Loading