try:from google.colab import outputprint("Running on CoLab") output.enable_custom_widget_manager()!pip install ipympl!pip install spatialmath-python!pip install roboticstoolbox-python>=1.0.2!pip install --no-deps rvc3python COLAB =TrueexceptModuleNotFoundError: COLAB =Falsefrom IPython.core.interactiveshell import InteractiveShellInteractiveShell.ast_node_interactivity ="last_expr_or_assign"from IPython.display import HTMLimport urllib.request# add RTB examples folder to the pathimport sys, os.pathimport roboticstoolbox as rtbimport RVC3# sys.path.append(os.path.join(rtb.__path__[0], 'examples'))sys.path.append(os.path.join(RVC3.__path__[0], "examples"))# standard importsimport numpy as npimport matplotlib.pyplot as pltimport mathfrom math import pinp.set_printoptions( linewidth=120, formatter={"float": lambda x: f"{0:8.4g}"ifabs(x) <1e-10elsef"{x:8.4g}"},)np.random.seed(0)from spatialmath import*from spatialmath.base import*from roboticstoolbox import quintic, trapezoidal, mtraj, mstraj, xplot, ctraj# Configure matplotlib for interactive plotstry:%matplotlib widgetprint("Using matplotlib widget backend for interactive plots")except:%matplotlib inlineprint("Using matplotlib inline backend")import matplotlib.pyplot as plt
Using matplotlib widget backend for interactive plots
There are some minor code changes compared to the book. These are to support the Matplotlib widget (ipympl) backend. This allows 3D plots to be rotated so the changes are worthwhile.
Animation Notes
This notebook has been updated to work better with different matplotlib backends:
Interactive animations: When %matplotlib widget is available, animations should work interactively
Fallback mode: If animations fail, static plots showing key frames will be displayed instead
HTML exports: The original HTML animation exports have been replaced with more robust alternatives
If you see “Animation error” messages, this is normal fallback behavior when the interactive backend is not available.
dt =0.05# time stepdef update():global orientation, wfor t in np.arange(0, 10, dt): wd =-np.linalg.inv(J) @ (np.cross(w, J @ w)) # (3.12) w += wd * dt orientation *= UnitQuaternion.EulerVec(w * dt)yield orientation.R# Use matplotlib widget for interactive animationplotvol3(new=True)try:# Use tranimate without extra dim parameter since it may be passed internally tranimate(update())exceptExceptionas e:print(f"Animation error: {e}")print("Showing static final orientation instead:")# Show final orientation as static plot final_orientation = orientationfor _ in update(): final_orientation = orientation# Use plotvol3 without conflicting parameters plotvol3(final_orientation.R, new=True)
plotvol3(new=True)try: pose.animate()exceptExceptionas e:print(f"Animation error: {e}")print("Showing static poses instead:")# Show a few key posesfor i in [0, 12, 25, 37, 49]:if i <len(pose): plotvol3(pose[i].R, alpha=0.6)
q0 = UnitQuaternion(R0)q1 = UnitQuaternion(R1);
qtraj = q0.interp(q1, 50)len(qtraj)
50
plotvol3(new=True)try: qtraj.animate()exceptExceptionas e:print(f"Animation error: {e}")print("Showing static trajectory instead:")# Show key frames of the trajectoryfor i in [0, 12, 25, 37, 49]:if i <len(qtraj): plotvol3(qtraj[i].R, alpha=0.6)
/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py:908: UserWarning: Animation was deleted without rendering anything. This is most likely not intended. To prevent deletion, assign the Animation to a variable, e.g. `anim`, that exists until you output the Animation using `plt.show()` or `anim.save()`.
warnings.warn(
for w in true.omega[:-1]:next= orientation[-1] @ UnitQuaternion.EulerVec(w * true.dt) orientation.append(next)len(orientation)
400
# orientation.animate(time=true.t)plotvol3(new=True)try: orientation.animate(time=true.t)exceptExceptionas e:print(f"Animation error: {e}")print("Showing orientation evolution at key time points:")# Show orientation at key time indices time_indices = [0,len(orientation) //4,len(orientation) //2,3*len(orientation) //4,-1, ]for i, idx inenumerate(time_indices):if idx <len(orientation): plotvol3(orientation[idx].R, alpha=0.7)print(f"Showing orientations at t={[true.t[i] for i in time_indices if i <len(true.t)]}" )
ERROR:tornado.application:Exception in callback <bound method TimerBase._on_timer of <matplotlib.backends.backend_webagg_core.TimerTornado object at 0x7d06ef195990>>
Traceback (most recent call last):
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/tornado/ioloop.py", line 945, in _run
val = self.callback()
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/backend_bases.py", line 1152, in _on_timer
ret = func(*args, **kwargs)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1450, in _step
still_going = super()._step(*args)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1138, in _step
self._draw_next_frame(framedata, self._blit)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1157, in _draw_next_frame
self._draw_frame(framedata)
File "/workspaces/rvc3-python/.venv/lib/pyt
ERROR:tornado.application:Exception in callback <bound method TimerBase._on_timer of <matplotlib.backends.backend_webagg_core.TimerTornado object at 0x7d06ef195990>>
Traceback (most recent call last):
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/tornado/ioloop.py", line 945, in _run
val = self.callback()
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/backend_bases.py", line 1152, in _on_timer
ret = func(*args, **kwargs)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1450, in _step
still_going = super()._step(*args)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1138, in _step
self._draw_next_frame(framedata, self._blit)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1157, in _draw_next_frame
self._draw_frame(framedata)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1789, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 233, in update
animation._draw(T)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 311, in _draw
x.draw(T)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 383, in draw
p = T @ self.p
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 4 is different from 3)
ERROR:tornado.application:Exception in callback <bound method TimerBase._on_timer of <matplotlib.backends.backend_webagg_core.TimerTornado object at 0x7d06ef195990>>
Traceback (most recent call last):
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/tornado/ioloop.py", line 945, in _run
val = self.callback()
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/backend_bases.py", line 1152, in _on_timer
ret = func(*args, **kwargs)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1450, in _step
still_going = super()._step(*args)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1138, in _step
self._draw_next_frame(framedata, self._blit)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1157, in _draw_next_frame
self._draw_frame(framedata)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/matplotlib/animation.py", line 1789, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 233, in update
animation._draw(T)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 311, in _draw
x.draw(T)
File "/workspaces/rvc3-python/.venv/lib/python3.10/site-packages/spatialmath/base/animate.py", line 383, in draw
p = T @ self.p
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 4 is different from 3)