From 02f7d3693e1310fe923c8b62e481a7d8262a2551 Mon Sep 17 00:00:00 2001 From: Peter Corke Date: Mon, 19 Oct 2026 18:41:00 +1000 Subject: [PATCH 1/2] docs(notebooks): modernise symbolic.ipynb for the current API and make it fast to run Co-Authored-By: Claude Sonnet 5.5 --- docs/notebooks/symbolic.ipynb | 127 +++++++++++++--------------------- 1 file changed, 50 insertions(+), 77 deletions(-) diff --git a/docs/notebooks/symbolic.ipynb b/docs/notebooks/symbolic.ipynb index e9daa05b6..461aa56ef 100644 --- a/docs/notebooks/symbolic.ipynb +++ b/docs/notebooks/symbolic.ipynb @@ -1,5 +1,28 @@ { "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + "
Robotics Toolbox for Python
\n", + "\n", + "

\n", + "
Symbolic computation
\n", + "

\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, @@ -560,7 +583,7 @@ "outputs": [], "source": [ "g = sym.symbol('g')\n", - "puma.gravity = [0, 0, g]" + "puma.gravity = [0, 0, -g]" ] }, { @@ -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]`." ] }, { @@ -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" ] }, { @@ -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" ] }, { @@ -781,7 +752,7 @@ "metadata": {}, "outputs": [], "source": [ - "m = tau[0].coeff(qdd[0]).args\n", + "m = tau_0.coeff(qdd[0]).args\n", "m" ] }, @@ -800,7 +771,7 @@ "metadata": {}, "outputs": [], "source": [ - "m = tau[0].coeff(qdd[1]).args\n", + "m = tau_0.coeff(qdd[1]).args\n", "m" ] }, @@ -819,7 +790,7 @@ "metadata": {}, "outputs": [], "source": [ - "c = tau[0].coeff(qd[0]).args\n", + "c = tau_0.coeff(qd[0]).args\n", "c" ] }, @@ -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" ] }, { @@ -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", @@ -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" ] }, @@ -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" ] }, { @@ -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" ] }, @@ -1086,13 +1059,6 @@ "source": [ "t1.expand().subs(sqdict)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { @@ -1154,6 +1120,13 @@ "_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" } }, "nbformat": 4, From 401ed5a30979eedf7dad808fd16995ecf938de72 Mon Sep 17 00:00:00 2001 From: Peter Corke Date: Mon, 19 Oct 2026 18:41:29 +1000 Subject: [PATCH 2/2] docs(notebooks): symbolic.ipynb asks for the ik extra, which installs SymPy in the browser Co-Authored-By: Claude Sonnet 5.5 --- docs/notebooks/symbolic.ipynb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/notebooks/symbolic.ipynb b/docs/notebooks/symbolic.ipynb index 461aa56ef..dbad257d6 100644 --- a/docs/notebooks/symbolic.ipynb +++ b/docs/notebooks/symbolic.ipynb @@ -74,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" ] }, { @@ -1127,6 +1127,11 @@ "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,