Skip to content
Open
Show file tree
Hide file tree
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
16 changes: 0 additions & 16 deletions docs/source/classes-2d.rst

This file was deleted.

10 changes: 0 additions & 10 deletions docs/source/classes-3d.rst

This file was deleted.

7 changes: 5 additions & 2 deletions docs/source/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ The classes ``SE3``, ``SO3``, ``SE2`` and ``SO2`` can provide colorized text out

.. image:: ../figs/colored_output.png
:width: 300

with rotational elements in red, translational elements in blue and constants in grey.

The foreground and background colors can be controlled using the following
Expand Down Expand Up @@ -538,8 +539,10 @@ A numpy column vector has shape ``(N,1)`` and a row vector
has shape ``(1,N)`` but functions also accept row ``(1,N)`` and column ``(N,1)``
where a vector argument is required.

.. warning:: For a user transitioning from MATLAB the most significant
differences are:
.. warning::

For a user transitioning from MATLAB the most significant differences are:

- the use of 1D arrays -- all MATLAB arrays have two dimensions,
even if one of them is equal to one.
- Iterating over a 1D NumPy array (N,) returns consecutive elements
Expand Down
2 changes: 1 addition & 1 deletion spatialmath/DualQuaternion.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ def SE3(self) -> SE3:

.. runblock:: pycon

>>> from spatialmath import DualQuaternion, SE3
>>> from spatialmath import UnitDualQuaternion, SE3
>>> T = SE3.Rand()
>>> print(T)
>>> d = UnitDualQuaternion(T)
Expand Down
2 changes: 1 addition & 1 deletion spatialmath/base/argcheck.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def isinteger(x: Any) -> bool:

.. runblock:: pycon

>>> from spatialmath.base import isscalar
>>> from spatialmath.base import isinteger
>>> isinteger(1)
>>> isinteger(1.2)

Expand Down
39 changes: 20 additions & 19 deletions spatialmath/base/graphics.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,42 +115,41 @@ def plot_point(
Plot one or more points, with optional text label.

- The color of the marker can be different to the color of the text, the
marker color is specified by a single letter in the marker string.
marker color is specified by a single letter in the marker string.

- A point can have multiple markers, given as a list, which will be
overlaid, for instance ``["rx", "ro"]`` will give a ⨂ symbol.
overlaid, for instance ``["rx", "ro"]`` will give a ⨂ symbol.

- The optional text label is placed to the right of the marker, and
vertically aligned.
vertically aligned.

- Multiple points can be marked if ``pos`` is a 2xn array or a list of
coordinate pairs. In this case:
coordinate pairs. In this case:

- all points have the same ``text`` label
- ``text`` can include the format string {} which is susbstituted for the
point index, starting at zero
point index, starting at zero
- ``text`` can be a tuple containing a format string followed by vectors
of shape(n). For example::
of shape(n). For example::

``("#{0} a={1:.1f}, b={2:.1f}", a, b)``
("#{0} a={1:.1f}, b={2:.1f}", a, b)

will label each point with its index (argument 0) and consecutive
elements of ``a`` and ``b`` which are arguments 1 and 2 respectively.

Example::

>>> from spatialmath.base import plotvol2, plot_text
>>> from spatialmath.base import plotvol2, plot_point
>>> plotvol2(5)
>>> plot_point((0, 0)) # plot default marker at coordinate (1,2)
>>> plot_point((0,0)) # plot default marker at coordinate (1,2)
>>> plot_point((1,1), 'r*') # plot red star at coordinate (1,2)
>>> plot_point((2,2), 'r*', 'foo') # plot red star at coordinate (1,2) and
label it as 'foo'
>>> plot_point((2,2), 'r*', 'foo') # plot red star at coordinate (1,2) and label it as 'foo'

.. plot::

from spatialmath.base import plotvol2, plot_text
from spatialmath.base import plotvol2, plot_point
ax = plotvol2(5)
plot_point((0, 0))
plot_point((0,0))
plot_point((1,1), 'r*')
plot_point((2,2), 'r*', 'foo')
ax.grid()
Expand Down Expand Up @@ -846,13 +845,15 @@ def plot_ellipse(
The ellipse is defined by :math:`x^T \mat{E} x = s^2` where :math:`x \in
\mathbb{R}^2` and :math:`s` is the scale factor.

.. note:: For some common cases we require :math:`\mat{E}^{-1}`, for example
.. note::
For some common cases we require :math:`\mat{E}^{-1}`, for example:

- for robot manipulability
:math:`\nu (\mat{J} \mat{J}^T)^{-1} \nu` i
:math:`\nu (\mat{J} \mat{J}^T)^{-1} \nu` i
- a covariance matrix
:math:`(x - \mu)^T \mat{P}^{-1} (x - \mu)`
so to avoid inverting ``E`` twice to compute the ellipse, we flag that
the inverse is provided using ``inverted``.
:math:`(x - \mu)^T \mat{P}^{-1} (x - \mu)`
so to avoid inverting ``E`` twice to compute the ellipse, we flag that
the inverse is provided using ``inverted``.

Returns a set of ``resolution`` that lie on the circumference of a circle
of given ``center`` and ``radius``.
Expand Down Expand Up @@ -1101,7 +1102,7 @@ def plot_ellipsoid(
.. note::

- If a confidence interval is given then ``E`` is interpretted as a covariance
matrix and the ellipse size is computed using an inverse chi-squared function.
matrix and the ellipse size is computed using an inverse chi-squared function.

:seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`
"""
Expand Down
3 changes: 2 additions & 1 deletion spatialmath/base/quaternions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,8 @@ def q2str(
fmt: Optional[str] = "{: .4f}",
) -> str:
"""
Format a quaternion as a string
Convert quaternion to compact single-line string


:arg q: unit-quaternion
:type q: array_like(4)
Expand Down
4 changes: 2 additions & 2 deletions spatialmath/base/symbolic.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def symbol(

- symbols named after greek letters will appear as greek letters
- underscore means subscript as it does in LaTex, so the symbols ``q``
above will be subscripted.
above will be subscripted.

:seealso: :func:`sympy.symbols`
"""
Expand Down Expand Up @@ -347,7 +347,7 @@ def det(x):
>>> R = rot2(theta)
>>> print(R)
>>> print(det(R))
>>> simplify(print(det(R)))
>>> print(simplify(det(R)))

.. note:: Converts to a SymPy ``Matrix`` and then back again.
"""
Expand Down
24 changes: 12 additions & 12 deletions spatialmath/base/transforms2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -715,13 +715,13 @@ def trnorm2(T: SE2Array) -> SE2Array:
The steps in normalization are:

#. If :math:`\mathbf{R} = [a, b]`
#. Form unit vectors :math:`\hat{b}
#. Form unit vectors :math:`\hat{b}`
#. Form the orthogonal planar vector :math:`\hat{a} = [\hat{b}_y -\hat{b}_x]`
#. Form the normalized SO(2) matrix :math:`\mathbf{R} = [\hat{a}, \hat{b}]`

.. runblock:: pycon

>>> from spatialmath.base import trnorm, troty
>>> from spatialmath.base import trnorm2, trot2
>>> from numpy import linalg
>>> T = trot2(45, 'deg', t=[3, 4])
>>> linalg.det(T[:2,:2]) - 1 # is a valid SO(3)
Expand Down Expand Up @@ -796,8 +796,8 @@ def tradjoint2(T):
>>> tr2adjoint2(T)

:Reference:
- Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
- `Lie groups for 2D and 3D Transformations <http://ethaneade.com/lie.pdf>_
- *Robotics, Vision & Control for Python*, Section 3.1, P. Corke, Springer 2023.
- `*Lie groups for 2D and 3D Transformations* <http://ethaneade.com/lie.pdf>`_

:SymPy: supported
"""
Expand Down Expand Up @@ -882,14 +882,14 @@ def trinterp2(start, end, s, shortest: bool = True):
:rtype: ndarray(3,3) or ndarray(2,2)
:raises ValueError: bad arguments

- ``trinterp2(None, T, S)`` is an SE(2) matrix interpolated
between identity when `S`=0 and `T` when `S`=1.
- ``trinterp2(T0, T1, S)`` as above but interpolated
between `T0` when `S`=0 and `T1` when `S`=1.
- ``trinterp2(None, R, S)`` is an SO(2) matrix interpolated
between identity when `S`=0 and `R` when `S`=1.
- ``trinterp2(R0, R1, S)`` as above but interpolated
between `R0` when `S`=0 and `R1` when `S`=1.
- ``trinterp2(None, T, s)`` is an sE(2) matrix interpolated
between identity when `s=0` and `T` when `s=1`.
- ``trinterp2(T0, T1, s)`` as above but interpolated
between `T0` when `s=0` and `T1` when `s=1`.
- ``trinterp2(None, R, s)`` is an sO(2) matrix interpolated
between identity when `s=0` and `R` when `s=1`.
- ``trinterp2(R0, R1, s)`` as above but interpolated
between `R0` when `s=0` and `R1` when `s=1`.

.. note:: Rotation angle is linearly interpolated.

Expand Down
4 changes: 3 additions & 1 deletion spatialmath/base/transforms3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ def transl(x, y=None, z=None):
.. note:: This function is compatible with the MATLAB version of the
Toolbox. It is unusual/weird in doing two completely different things
inside the one function.

:seealso: :func:`~spatialmath.base.transforms2d.transl2`
:SymPy: supported
"""
Expand Down Expand Up @@ -3390,7 +3391,8 @@ def tranimate(T: Union[SO3Array, SE3Array], **kwargs) -> str:
:type wait: bool
:param movie: name of file to write MP4 movie into
:type movie: str
:param **kwargs: arguments passed to ``trplot``
:param kwargs: arguments passed to ``trplot``
:type kwargs: dict

- ``tranimate(T)`` where ``T`` is an SO(3) or SE(3) matrix, animates a 3D
coordinate frame moving from the world frame to the frame ``T`` in
Expand Down
4 changes: 2 additions & 2 deletions spatialmath/base/vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ def unittwist2(S: ArrayLike3, tol: float = 20) -> Union[R3, None]:
.. runblock:: pycon

>>> from spatialmath.base import *
>>> unittwist2([2, 4, 2)
>>> unittwist2([2, 4, 2])
>>> unittwist2([2, 0, 0])

.. note:: Returns None if the twist has zero magnitude
Expand Down Expand Up @@ -501,7 +501,7 @@ def unittwist2_norm(
.. runblock:: pycon

>>> from spatialmath.base import *
>>> unittwist2([2, 4, 2)
>>> unittwist2([2, 4, 2])
>>> unittwist2([2, 0, 0])

.. note:: Returns (None, None) if the twist has zero magnitude
Expand Down
34 changes: 22 additions & 12 deletions spatialmath/baseposematrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,14 @@ def log(self, twist: Optional[bool] = False) -> Union[NDArray, List[NDArray]]:
"""
Logarithm of pose (superclass method)

:param twist: return twist coordinates vector rather than matrix, defaults to False
:type twist: bool, optional
:return: logarithm
:rtype: ndarray
:raises: ValueError

An efficient closed-form solution of the matrix logarithm.
An efficient closed-form solution of the matrix logarithm. By default the
result is a structured matrix

===== ====== ===============================
Input Output
Expand All @@ -352,19 +355,22 @@ def log(self, twist: Optional[bool] = False) -> Union[NDArray, List[NDArray]]:
SO3 (3,3) skew-symmetric SE3 (4,4) augmented skew-symmetric
===== ====== ===============================

but if ``twist=True`` the result is a vector, the twist coordinates, containing
the unique elements with translational elements first. The rotational
elements are also known as the exponential coordinates of the rotation.

Example::

>>> x = SE3.Rx(0.3)
>>> y = x.log()
>>> y
array([[ 0. , -0. , 0. , 0. ],
[ 0. , 0. , -0.3, 0. ],
[-0. , 0.3, 0. , 0. ],
[ 0. , 0. , 0. , 0. ]])
.. runblock:: pycon

>>> from spatialmath import SO3, SE3
>>> T = SE3.Rx(0.3)
>>> T.log()
>>> T.log(twist=True)
>>> R = SO3.Rx(0.3)
>>> R.log(twist=True) # exponential coordinates

:seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
:func:`~spatialmath.base.transforms3d.trlog`
:seealso: :func:`~spatialmath.base.transforms2d.trlog2` :func:`~spatialmath.base.transforms3d.trlog`

:SymPy: not supported
"""
Expand Down Expand Up @@ -395,6 +401,9 @@ def interp(
:return: interpolated pose
:rtype: same as ``self``

This interpolation is given by a scalar or the number of equally spaced
steps:

- ``X.interp(Y, s)`` interpolates pose between X between when s=0
and Y when s=1.
- ``X.interp(Y, N)`` interpolates pose between X and Y in ``N`` steps.
Expand All @@ -417,6 +426,7 @@ def interp(

- For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
- Values of ``s`` outside the range [0,1] are silently clipped

:seealso: :func:`interp1`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.base.transforms2d.trinterp2`

:SymPy: not supported
Expand Down Expand Up @@ -707,8 +717,8 @@ def printline(self, *args, **kwargs) -> None:
>>> x.printline()
>>> x = SE3.Rx([0.2, 0.3])
>>> x.printline()
>>> x.printline('angvec')
>>> x.printline(orient='angvec', fmt="{:.6f}")
>>> x.printline(orient="angvec")
>>> x.printline(orient="angvec", fmt="{:.6f}")
>>> x = SE2(1, 2, 0.3)
>>> x.printline()

Expand Down
4 changes: 2 additions & 2 deletions spatialmath/geom2d.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,9 +653,9 @@ def vertices(self, unique: bool = True) -> Points2:
.. runblock:: pycon

>>> from spatialmath import Polygon2
>>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
>>> p = Polygon2([(1, 2), (3, 2), (2, 4), (1,2)])
>>> p.vertices()
>>> p.vertices(closed=True)
>>> p.vertices(unique=True)
"""
vertices = self.path.vertices.T
if unique:
Expand Down
Loading
Loading