spatialmath-python API Reference

Full documentation for spatialmath-python (1.1.16)

spatialmath-python.BSplineSE3
Python Library Documentation: class BSplineSE3 in module spatialmath.spline

class BSplineSE3(SplineSE3)
 |  BSplineSE3(control_poses: List[spatialmath.pose3d.SE3], degree: int = 3, knots: Optional[List[float]] = None) -> None
 |
 |  A class to parameterize a trajectory in SE3 with a 6-dimensional B-spline.
 |
 |  The SE3 control poses are converted to se3 twists (the lie algebra) and a B-spline
 |  is created for each dimension of the twist, using the corresponding element of the twists
 |  as the control point for the spline.
 |
 |  For detailed information about B-splines, please see this wikipedia article.
 |  https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline
 |
 |  Method resolution order:
 |      BSplineSE3
 |      SplineSE3
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __call__(self, t: float) -> spatialmath.pose3d.SE3
 |      Returns pose of spline at t.
 |
 |      t: Normalized time value [0,1] to evaluate the spline at.
 |
 |  __init__(self, control_poses: List[spatialmath.pose3d.SE3], degree: int = 3, knots: Optional[List[float]] = None) -> None
 |      Construct BSplineSE3 object. The default arguments generate a cubic B-spline
 |      with uniformly spaced knots.
 |
 |      - control_poses: list of SE3 objects that govern the shape of the spline.
 |      - degree: int that controls degree of the polynomial that governs any given point on the spline.
 |      - knots: list of floats that govern which control points are active during evaluating the spline
 |      at a given t input. If none, they are automatically, uniformly generated based on number of control poses and
 |      degree of spline on the range [0,1].
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SplineSE3:
 |
 |  visualize(self, sample_times: List[float], input_trajectory: Optional[List[spatialmath.pose3d.SE3]] = None, pose_marker_length: float = 0.2, animate: bool = False, repeat: bool = True, ax: Optional[matplotlib.axes._axes.Axes] = None) -> None
 |      Displays an animation of the trajectory with the control poses against an optional input trajectory.
 |
 |      Args:
 |          sample_times: which times to sample the spline at and plot
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from SplineSE3:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.BasePoseMatrix
Python Library Documentation: class BasePoseMatrix in module spatialmath.baseposematrix

class BasePoseMatrix(spatialmath.baseposelist.BasePoseList)
 |  BasePoseMatrix(*args, **kwargs)
 |
 |  Superclass for SO(N) and SE(N) objects
 |
 |  Subclasses are:
 |
 |  - ``SO2`` representing elements of SO(2) which describe rotations in 2D
 |  - ``SE2`` representing elements of SE(2) which describe rigid-body motion in 2D
 |  - ``SO3`` representing elements of SO(3) which describe rotations in 3D
 |  - ``SE3`` representing elements of SE(3) which describe rigid-body motion in 3D
 |
 |  Arithmetic operators are overloaded but the operation they perform depend
 |  on the types of the operands.  For example:
 |
 |  - ``*`` will compose two instances of the same subclass, and the result will
 |    be an instance of the same subclass, since this is a group operator.
 |  - ``+`` will add two instances of the same subclass, and the result will be
 |    a matrix, not an instance of the same subclass, since addition is not a group operator.
 |
 |  These classes all inherit from ``UserList`` which enables them to
 |  represent a sequence of values, ie. an ``SE3`` instance can contain
 |  a sequence of SE(3) values.  Most of the Python ``list`` operators
 |  are applicable::
 |
 |      >>> x = SE3()  # new instance with identity matrix value
 |      >>> len(x)     # it is a sequence of one value
 |      1
 |      >>> x.append(x)  # append to itself
 |      >>> len(x)       # it is a sequence of two values
 |      2
 |      >>> x[1]         # the element has a 4x4 matrix value
 |      SE3([
 |      array([[1., 0., 0., 0.],
 |             [0., 1., 0., 0.],
 |             [0., 0., 1., 0.],
 |          [0., 0., 0., 1.]]) ])
 |      >>> x[1] = SE3.Rx(0.3)  # set an elements of the sequence
 |      >>> x.reverse()         # reverse the elements in the sequence
 |      >>> del x[1]            # delete an element
 |
 |  For console printing colorization is supported if the package ``colored``
 |  is installed.  Class variables control the colorization and can be assigned
 |  to at any time.
 |
 |  ===============  ===================  ============================================
 |  Variable         Default              Description
 |  ===============  ===================  ============================================
 |  _rotcolor        'red'                Foreground color of rotation submatrix
 |  _transcolor      'blue'               Foreground color of rotation submatrix
 |  _constcolor      'grey_50'            Foreground color of matrix constant elements
 |  _bgcolor         None                 Background color of matrix
 |  _indexcolor      (None, 'yellow_2')   Foreground, background color of index tag
 |  _format          '{:< 12g}'           Format string for each matrix element
 |  _suppress_small  True                 Suppress *small* values, set to zero
 |  _suppress_tol    100                  Threshold for *small* values in eps units
 |  _ansimatrix      False                Display with matrix brackets
 |  ===============  ===================  ============================================
 |
 |  If color is specified as ``None`` it means no colorization is performed.
 |
 |  For example::
 |
 |      >> SE3._bgcolor = None
 |      >> SE3._indexcolor = ('green', None)
 |
 |  .. note:: The ``_ansimatrix`` option requires that the ``ansitable`` package
 |      is installed.  It does not currently support colorization of elements.
 |
 |  Method resolution order:
 |      BasePoseMatrix
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __add__(left, right)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Add the elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
 |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
 |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ========================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ========================
 |      Pose             Pose             NxN matrix   element-wise matrix sum
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ========================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar + Pose is handled by :meth:`__radd__`
 |          #. Addition is commutative
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose addition either or both operands may hold more than one value which
 |      results in the sum holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``sum = left + right``
 |       1          M             M    ``sum[i] = left + right[i]``
 |       N          1             M    ``sum[i] = left[i] + right``
 |       M          M             M    ``sum[i] = left[i] + right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __eq__(left, right: 'Self') -> 'bool'
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for equality
 |
 |      ``X == Y`` is true of the poses are of the same type and numerically
 |      equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the equality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``eq = left == right``
 |       1          M             M    ``eq[i] = left == right[i]``
 |       N          1             M    ``eq[i] = left[i] == right``
 |       M          M             M    ``eq[i] = left[i] == right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __iadd__(left, right)
 |      Overloaded ``+=`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
 |      - ``X += s`` elementwise addition of the matrix elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__add__``
 |
 |  __imul__(left, right)
 |      Overloaded ``*=`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
 |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__mul__``
 |
 |  __isub__(left, right: 'Self')
 |      Overloaded ``-=`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises: ValueError
 |
 |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
 |        and ``Y`` and places the result in ``X``
 |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
 |        and the scalar ``s`` and places the result in ``X``
 |
 |      :seealso: ``__sub__``
 |
 |  __itruediv__(left, right)
 |      Overloaded ``/=`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
 |      - ``X /= s`` performs elementwise division of the elements of ``X``
 |        by ``s`` and places the result in ``X``
 |
 |      :seealso: ``__truediv__``
 |
 |  __matmul__(left, right)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :return: Product of two operands with normalization
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
 |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
 |        and places the result in ``X``
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally
 |          update over many cycles.
 |
 |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Pose composition, scaling or vector transformation:
 |
 |      - ``X * Y`` compounds the poses ``X`` and ``Y``
 |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
 |
 |      ==============   ==============   ===========  ======================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ======================
 |      Pose             Pose             Pose         matrix product
 |      Pose             scalar           NxN matrix   element-wise product
 |      scalar           Pose             NxN matrix   element-wise product
 |      Pose             N-vector         N-vector     vector transform
 |      Pose             NxM matrix       NxM matrix   transform each column
 |      ==============   ==============   ===========  ======================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar x Pose is handled by __rmul__`
 |          #. Scalar multiplication is commutative but the result is not a group
 |             operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
 |          SE3(array([[0., 0., 1., 0.],
 |                  [1., 0., 0., 0.],
 |                  [0., 1., 0., 0.],
 |                  [0., 0., 0., 1.]]))
 |          >>> SE3.Rx(pi/2) * 2
 |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
 |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
 |
 |      For vector transformation there are three cases:
 |
 |      =========  ===========  =====  ==========================
 |            Multiplicands             Product
 |      ----------------------  ---------------------------------
 |      len(left)  right.shape  shape  operation
 |      =========  ===========  =====  ==========================
 |      1          (N,)         (N,)   vector transformation
 |      M          (N,)         (N,M)  vector transformations
 |      1          (N,M)        (N,M)  column transformation
 |      =========  ===========  =====  ==========================
 |
 |      .. note::
 |          - The vector is an array-like, a 1D NumPy array or a list/tuple
 |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
 |            form, transformed, then converted back to Euclidean form.
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * [0, 1, 0]
 |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
 |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
 |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :return: Inequality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for inequality
 |
 |      - ``X != Y`` is true of the poses are of the same type but not numerically
 |        equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the inequality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``ne = left != right``
 |       1          M             M    ``ne[i] = left != right[i]``
 |       N          1             M    ``ne[i] = left[i] != right``
 |       M          M             M    ``ne[i] = left[i] != right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __pow__(self, n: 'int') -> 'Self'
 |      Overloaded ``**`` operator (superclass method)
 |
 |      :param n: exponent
 |      :type n: int
 |      :return: pose to the power ``n``
 |      :rtype: pose instance
 |
 |      ``X**n`` raise all values held in `X` to the specified power using repeated
 |      multiplication.  If ``n`` < 0 then the result is inverted.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.1) ** 2
 |          >>> SE3.Rx([0, 0.1]) ** 2
 |
 |  __radd__(right, left)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__add__`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> repr(x)
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Left-multiplication
 |
 |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
 |        elements of ``X`` by ``s`` and the result is a NumPy array.
 |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
 |        of ``A`` and ``X`` and the result is a NumPy array.
 |
 |      :seealso: :func:`__mul__`
 |
 |  __rsub__(right, left: 'Self')
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__sub__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of pose (superclass method)
 |
 |      :return: readable representation of the pose
 |      :rtype: str
 |
 |      Convert the pose's matrix value to a simple grid of numbers.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x)
 |
 |      Notes:
 |
 |          - By default, the output is colorised for an ANSI terminal console:
 |
 |              * red: rotational elements
 |              * blue: translational elements
 |              * white: constant elements
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Subtract elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
 |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
 |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ==============================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ==============================
 |      Pose             Pose             NxN matrix   element-wise matrix difference
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ==============================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar - Pose is handled by :meth:`__rsub__`
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose subtraction either or both operands may hold more than one value which
 |      results in the difference holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``diff = left - right``
 |       1          M             M    ``diff[i] = left - right[i]``
 |       N          1             M    ``diff[i] = left[i] - right``
 |       M          M             M    ``diff[i] = left[i]  right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __truediv__(left, right)
 |      Overloaded ``/`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      Pose composition or scaling:
 |
 |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
 |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
 |
 |      ==============   ==============   ===========  =========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   --------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  =========================
 |      Pose             Pose             Pose         matrix product by inverse
 |      Pose             scalar           NxN matrix   element-wise division
 |      ==============   ==============   ===========  =========================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar multiplication is not a group operation so the result will
 |             be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |  animate(self, *args, start=None, **kwargs) -> 'None'
 |      Plot pose object as an animated coordinate frame (superclass method)
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: same as ``self``
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
 |        from the origin in either 2D or 3D.  There are many options, see the
 |        links below.
 |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
 |        frame moving from pose ``X1``, in either 2D or 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=SE3.Ry(0.2))
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
 |
 |  conjugation(self, A: 'NDArray') -> 'NDArray'
 |      Matrix conjugation
 |
 |      :param A: matrix to conjugate
 |      :type A: ndarray
 |      :return: conjugated matrix
 |      :rtype: ndarray
 |
 |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
 |      is the current object.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO2
 |          >>> import numpy as np
 |          >>> R = SO2(0.5)
 |          >>> A = np.array([[10, 0], [0, 1]])
 |          >>> print(R * A * R.inv())
 |          >>> print(R.conjugation(A))
 |
 |  det(self) -> 'Tuple[float, Rn]'
 |      Determinant of rotational component (superclass method)
 |
 |      :return: Determinant of rotational component
 |      :rtype: float or NumPy array
 |
 |      ``x.det()`` is the determinant of the rotation component of the values
 |      of ``x``.
 |
 |      Example::
 |
 |          >>> x=SE3.Rand()
 |          >>> x.det()
 |          1.0000000000000004
 |          >>> x=SE3.Rand(N=2)
 |          >>> x.det()
 |          [0.9999999999999997, 1.0000000000000002]
 |
 |      :SymPy: not supported
 |
 |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
 |      Interpolate between poses (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :param shortest: take the shortest path along the great circle for the rotation
 |      :type shortest: bool, default to True
 |      :return: interpolated pose
 |      :rtype: same as ``self``
 |
 |      - ``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.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
 |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
 |          >>> x.interp(y, 0)    # this is x
 |          >>> x.interp(y, 1)    # this is y
 |          >>> x.interp(y, 0.5)  # this is in between
 |          >>> z = x.interp(y, 11)  # in 11 steps
 |          >>> len(z)
 |          >>> z[0]              # this is x
 |          >>> z[5]              # this is in between
 |
 |      .. note::
 |
 |          - 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
 |
 |  interp1(self, s: 'float' = None) -> 'Self'
 |      Interpolate pose (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1
 |      :type s: array_like
 |      :return: interpolated pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
 |
 |          ======  ======  ===========  ===============================
 |          len(X)  len(s)  len(result)  Result
 |          ======  ======  ===========  ===============================
 |          1       1       1            Y = interp(X, s)
 |          M       1       M            Y[i] = interp(X[i], s)
 |          1       M       M            Y[i] = interp(X, s[i])
 |          ======  ======  ===========  ===============================
 |
 |      Example::
 |
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x.interp(0))
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |          >>> print(x.interp(1))
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
 |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |          >>> y = x.interp(x, np.linspace(0, 1, 10))
 |          >>> len(y)
 |          10
 |          >>> y[5]
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
 |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |
 |      Notes:
 |
 |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
 |
 |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
 |
 |      :SymPy: not supported
 |
 |  ishom(self) -> 'bool'
 |      Test if object belongs to SE(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          True
 |
 |  ishom2(self) -> 'bool'
 |      Test if object belongs to SE(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          True
 |
 |  isrot(self) -> 'bool'
 |      Test if object belongs to SO(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          False
 |
 |  isrot2(self) -> 'bool'
 |      Test if object belongs to SO(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          False
 |
 |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
 |      Logarithm of pose (superclass method)
 |
 |      :return: logarithm
 |      :rtype: ndarray
 |      :raises: ValueError
 |
 |      An efficient closed-form solution of the matrix logarithm.
 |
 |      =====  ======  ===============================
 |      Input         Output
 |      -----  ---------------------------------------
 |      Pose   Shape   Structure
 |      =====  ======  ===============================
 |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
 |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
 |      =====  ======  ===============================
 |
 |      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. ]])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
 |      :func:`~spatialmath.base.transforms3d.trlog`
 |
 |      :SymPy: not supported
 |
 |  norm(self) -> 'Self'
 |      Normalize pose (superclass method)
 |
 |      :return: pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
 |        part of all values has been adjusted to ensure it is a proper orthogonal
 |        matrix rotation.
 |
 |      Example::
 |
 |          >>> x = SE3()
 |          >>> y = x.norm()
 |          >>> y
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |
 |      Notes:
 |
 |      #. Only the direction of A vector (the z-axis) is unchanged.
 |      #. Used to prevent finite word length arithmetic causing transforms to
 |         become 'unnormalized'.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
 |
 |  plot(self, *args, **kwargs) -> 'None'
 |      Plot pose object as a coordinate frame (superclass method)
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
 |        2D or 3D.  There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.plot(frame='A', color='green')
 |
 |      .. plot::
 |
 |          from spatialmath import SE3
 |          X = SE3.Rx(0.3)
 |          X.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
 |
 |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
 |      Print pose as a matrix (superclass method)
 |
 |      :param label: label to print before the matrix, defaults to None
 |      :type label: str, optional
 |      :param file: file to write to, defaults to None
 |      :type file: file object, optional
 |
 |      Print the pose as a matrix, with an optional line beforehand.  By default
 |      the matrix is printed to stdout.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3().print()
 |          >>> SE3().print("pose is:")
 |
 |      :seealso: :meth:`printline` :meth:`strline`
 |
 |  printline(self, *args, **kwargs) -> 'None'
 |      Print pose in compact single line format (superclass method)
 |
 |      :param arg: value for orient option, optional
 |      :type arg: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param file: file to write formatted string to. [default, stdout]
 |      :type file: file object
 |
 |      Print pose in a compact single line format. If ``X`` has multiple
 |      values, print one per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.printline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.printline()
 |          >>> x.printline('angvec')
 |          >>> x.printline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.printline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
 |
 |  prod(self, norm=False, check=True) -> 'Self'
 |      Product of elements (superclass method)
 |
 |      :param norm: normalize the product, defaults to False
 |      :type norm: bool, optional
 |      :param check: check that computed matrix is valid member of group, default True
 |      :bool check: bool, optional
 |      :return: Product of elements
 |      :rtype: pose instance
 |
 |      ``x.prod()`` is the product of the values held by ``x``, ie.
 |      :math:`\prod_i^N T_i`.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
 |          >>> x.prod()
 |
 |      .. note:: When compounding many transformations the product may become
 |          denormalized resulting in a result that is not a proper member of the
 |          group.  You can either disable membership checking by ``check=False``
 |          which is risky, or normalize the result by ``norm=True``.
 |
 |  simplify(self) -> 'Self'
 |      Symbolically simplify matrix values (superclass method)
 |
 |      :return: pose with symbolic elements
 |      :rtype: pose instance
 |
 |      Apply symbolic simplification to every element of every value in the
 |      pose instance.
 |
 |      Example::
 |
 |          >>> a = SE3.Rx(sympy.symbols('theta'))
 |          >>> b = a * a
 |          >>> b
 |          SE3(array([[1, 0, 0, 0.0],
 |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
 |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
 |          [0.0, 0, 0, 1.0]], dtype=object)
 |          >>> b.simplify()
 |          SE3(array([[1, 0, 0, 0],
 |          [0, cos(2*theta), -sin(2*theta), 0],
 |          [0, sin(2*theta), cos(2*theta), 0],
 |          [0, 0, 0, 1.00000000000000]], dtype=object))
 |
 |      .. todo:: No need to simplify the constants in bottom row
 |
 |      :SymPy: supported
 |
 |  stack(self) -> 'NDArray'
 |      Convert to 3-dimensional matrix
 |
 |      :return: 3-dimensional NumPy array
 |      :rtype: ndarray(n,n,m)
 |
 |      Converts the value to a 3-dimensional NumPy array where the values are
 |      stacked along the third axis.  The first two dimensions are given by
 |      ``self.shape``.
 |
 |  strline(self, *args, **kwargs) -> 'str'
 |      Convert pose to compact single line string (superclass method)
 |
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: pose in string format
 |      :rtype: str
 |
 |      Convert pose in a compact single line format. If ``X`` has multiple
 |      values, the string has one pose per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.strline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.strline()
 |          >>> x.strline('angvec')
 |          >>> x.strline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.strline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(cls, *args, **kwargs)
 |      Create the subclass instance (superclass method)
 |
 |      Create a new instance and call the superclass initializer to enable the
 |      ``UserList`` capabilities.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  N
 |      Dimension of the object's group (superclass property)
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
 |      This corresponds to the dimension of the space, 2D or 3D, to which these
 |      rotations or rigid-body motions apply.
 |
 |      Example::
 |
 |          >>> SE3().N
 |          3
 |          >>> SE2().N
 |          2
 |
 |  about
 |      Succinct summary of object type and length (superclass property)
 |
 |      :return: succinct summary
 |      :rtype: str
 |
 |      Displays the type and the number of elements in compact form, for
 |      example::
 |
 |          >>> x = SE3([SE3() for i in range(20)])
 |          >>> len(x)
 |          20
 |          >>> print(x.about)
 |          SE3[20]
 |
 |  isSE
 |      Test if object belongs to SE(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SE2 or SE3
 |      :rtype: bool
 |
 |  isSO
 |      Test if object belongs to SO(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SO2 or SO3
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset({'_identity', 'isvalid', 'shape'})
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Static methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  isvalid(x, check=True)
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  shape
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __init__(self, initlist=None)
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __len__(self)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.DualQuaternion
Python Library Documentation: class DualQuaternion in module spatialmath.DualQuaternion

class DualQuaternion(builtins.object)
 |  DualQuaternion(real: 'Quaternion' = None, dual: 'Quaternion' = None)
 |
 |  A dual number is an ordered pair :math:`\hat{a} = (a, b)` or written as
 |  :math:`a + \epsilon b` where :math:`\epsilon^2 = 0`.
 |
 |  A dual quaternion can be considered as either:
 |
 |  - a quaternion with dual numbers as coefficients
 |  - a dual of quaternions, written as an ordered pair of quaternions
 |
 |  The latter form is used here.
 |
 |  :References:
 |
 |  - http://web.cs.iastate.edu/~cs577/handouts/dual-quaternion.pdf
 |  - https://en.wikipedia.org/wiki/Dual_quaternion
 |
 |  .. warning:: Unlike the other spatial math classes, this class does not
 |    (yet) support multiple values per object.
 |
 |  :seealso: :func:`UnitDualQuaternion`
 |
 |  Methods defined here:
 |
 |  __add__(left, right: 'DualQuaternion') -> 'Self'
 |      Sum of two dual quaternions
 |
 |      :return: Product
 |      :rtype: DualQuaternion
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d + d
 |
 |  __init__(self, real: 'Quaternion' = None, dual: 'Quaternion' = None)
 |      Construct a new dual quaternion
 |
 |      :param real: real quaternion
 |      :type real: Quaternion or UnitQuaternion
 |      :param dual: dual quaternion
 |      :type dual: Quaternion or UnitQuaternion
 |      :raises ValueError: incorrect parameters
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> print(d)
 |          >>> d = DualQuaternion([1, 2, 3, 4,  5, 6, 7, 8])
 |          >>> print(d)
 |
 |      The dual number is stored internally as two quaternion, respectively
 |      called ``real`` and ``dual``.
 |
 |  __mul__(left, right: 'Self') -> 'Self'
 |      Product of dual quaternion
 |
 |      - ``dq1 * dq2`` is a dual quaternion representing the product of
 |        ``dq1`` and ``dq2``.  If both are unit dual quaternions, the product
 |        will be a unit dual quaternion.
 |      - ``dq * p`` transforms the point ``p`` (3) by the unit dual quaternion
 |        ``dq``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d * d
 |
 |  __repr__(self) -> 'str'
 |      Return repr(self).
 |
 |  __str__(self) -> 'str'
 |      String representation of dual quaternion
 |
 |      :return: compact string representation
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> str(d)
 |
 |  __sub__(left, right: 'DualQuaternion') -> 'Self'
 |      Difference of two dual quaternions
 |
 |      :return: Product
 |      :rtype: DualQuaternion
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d - d
 |
 |  conj(self) -> 'Self'
 |      Conjugate of dual quaternion
 |
 |      :return: Conjugate
 |      :rtype: DualQuaternion
 |
 |      There are several conjugates defined for a dual quaternion. This one
 |      mirrors conjugation for a regular quaternion.  For the dual quaternion
 |      :math:`(p, q)` it returns :math:`(p^*, q^*)`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.conj()
 |
 |  matrix(self) -> 'R8x8'
 |      Dual quaternion as a matrix
 |
 |      :return: Matrix represensation
 |      :rtype: ndarray(8,8)
 |
 |      Dual quaternion multiplication can also be written as a matrix-vector
 |      product.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.matrix()
 |          >>> d.matrix() @ d.vec
 |          >>> d * d
 |
 |  norm(self) -> 'Tuple[float, float]'
 |      Norm of a dual quaternion
 |
 |      :return: Norm as a dual number
 |      :rtype: 2-tuple
 |
 |      The norm of a ``UnitDualQuaternion`` is unity, represented by the dual
 |      number (1,0).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.norm()  # norm is a dual number
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  Pure(x: 'ArrayLike3') -> 'Self'
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  vec
 |      Dual quaternion as a vector
 |
 |      :return: Vector represensation
 |      :rtype: ndarray(8)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.vec
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Ellipse
Python Library Documentation: class Ellipse in module spatialmath.geom2d

class Ellipse(builtins.object)
 |  Ellipse(radii: 'Optional[ArrayLike2]' = None, E: 'Optional[NDArray]' = None, centre: 'ArrayLike2' = (0, 0), theta: 'Optional[float]' = None)
 |
 |  Methods defined here:
 |
 |  __init__(self, radii: 'Optional[ArrayLike2]' = None, E: 'Optional[NDArray]' = None, centre: 'ArrayLike2' = (0, 0), theta: 'Optional[float]' = None)
 |      Create an ellipse
 |
 |      :param radii: radii of ellipse, defaults to None
 |      :type radii: arraylike(2), optional
 |      :param E: 2x2 matrix describing ellipse, defaults to None
 |      :type E: ndarray(2,2), optional
 |      :param centre: centre of ellipse, defaults to (0, 0)
 |      :type centre: arraylike(2), optional
 |      :param theta: orientation of ellipse, defaults to None
 |      :type theta: float, optional
 |      :raises ValueError: bad parameters
 |
 |      The ellipse shape can be specified by ``radii`` and ``theta`` or by a
 |      symmetric 2x2 matrix ``E``.
 |
 |      Internally the ellipse is represented by a symmetric matrix :math:`\mat{E} \in \mathbb{R}^{2\times 2}`
 |      and its centre coordinate :math:`\vec{x}_0 \in \mathbb{R}^2` such that
 |
 |      .. math::
 |
 |          (\vec{x} - \vec{x}_0)^{\top} \mat{E} \, (\vec{x} - \vec{x}_0) = 1
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> import numpy as np
 |          >>> Ellipse(radii=(1,2), theta=0)
 |          >>> Ellipse(E=np.array([[1, 1], [1, 2]]))
 |
 |  __repr__(self) -> 'str'
 |      Return repr(self).
 |
 |  __str__(self) -> 'str'
 |      Return str(self).
 |
 |  contains(self, p)
 |      Test if points are contained by ellipse
 |
 |      :param p: point or points to test
 |      :type p: arraylike(2), ndarray(2,N)
 |      :return: true if point is contained within ellipse
 |      :rtype: bool or list(bool)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.contains((3,4))
 |          >>> e.contains((0,0))
 |
 |  plot(self, **kwargs) -> 'None'
 |      Plot ellipse
 |
 |      :param kwargs: arguments passed to :func:`~spatialmath.base.graphics.plot_ellipse`
 |      :return: list of artists
 |      :rtype: _type_
 |
 |      Example::
 |
 |          >>> from spatialmath import Ellipse
 |          >>> from spatialmath.base import plotvol2
 |          >>> plotvol2(5)
 |          >>> e = Ellipse(E=np.array([[1, 1], [1, 2]]))
 |          >>> e.plot()
 |          >>> e.plot(filled=True, color='r')
 |
 |
 |      .. plot::
 |
 |          from spatialmath import Ellipse
 |          from spatialmath.base import plotvol2
 |          ax = plotvol2(5)
 |          e = Ellipse(E=np.array([[1, 1], [1, 2]]))
 |          e.plot()
 |          ax.grid()
 |
 |      .. plot::
 |
 |          from spatialmath import Ellipse
 |          from spatialmath.base import plotvol2
 |          ax = plotvol2(5)
 |          e = Ellipse(E=np.array([[1, 1], [1, 2]]))
 |          e.plot(filled=True, color='r')
 |          ax.grid()
 |
 |      :seealso: :func:`~spatialmath.base.graphics.plot_ellipse`
 |
 |  points(self, resolution=20) -> 'Points2'
 |      Generate perimeter points
 |
 |      :param resolution: number of points on circumferance, defaults to 20
 |      :type resolution: int, optional
 |      :return: set of perimeter points
 |      :rtype: Points2
 |
 |      Return a set of ``resolution`` points on the perimeter of the ellipse.  The perimeter
 |      set is not closed, that is, last point != first point.
 |
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.points()[:,:5]  # first 5 points
 |
 |      :seealso: :meth:`polygon` :func:`~spatialmath.base.graphics.ellipse`
 |
 |  polygon(self, resolution=10) -> 'Polygon2'
 |      Approximate with a polygon
 |
 |      :param resolution: number of polygon vertices, defaults to 20
 |      :type resolution: int, optional
 |      :return: a polygon approximating the ellipse
 |      :rtype: :class:`Polygon2` instance
 |
 |      Return a polygon instance with ``resolution`` vertices.  A :class:`Polygon2`` can be
 |      used for intersection testing with lines or other polygons.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.polygon()
 |
 |      :seealso: :meth:`points`
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  FromPerimeter(p: 'Points2') -> 'Self'
 |      Create an ellipse that fits a set of perimeter points
 |
 |      :param p: a set of 2D perimeter points
 |      :type p: ndarray(2,N)
 |      :return: an ellipse instance
 |      :rtype: Ellipse
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> import numpy as np
 |          >>> eref = Ellipse(radii=(1, 2), theta=np.pi / 4, centre=[3, 4])
 |          >>> perim = eref.points()
 |          >>> print(perim.shape)
 |          >>> Ellipse.FromPerimeter(perim)
 |
 |      :seealso: :meth:`points`
 |
 |  FromPoints(p) -> 'Self'
 |      Create an equivalent ellipse from a set of interior points
 |
 |      :param p: a set of 2D interior points
 |      :type p: ndarray(2,N)
 |      :return: an ellipse instance
 |      :rtype: Ellipse
 |
 |      Computes the ellipse that has the same inertia as the set of points.
 |
 |      :seealso: :meth:`FromPerimeter`
 |
 |  Polynomial(e: 'ArrayLike', p: 'Optional[ArrayLike2]' = None) -> 'Self'
 |      Create an ellipse from polynomial
 |
 |      :param e: polynomial coeffients :math:`e` or :math:`\eta`
 |      :type e: arraylike(4) or arraylike(5)
 |      :param p: point to set scale
 |      :type p: array_like(2), optional
 |      :return: an ellipse instance
 |      :rtype: Ellipse
 |
 |      An ellipse can be specified by a polynomial :math:`\vec{e} \in \mathbb{R}^6`
 |
 |      .. math::
 |
 |          e_0 x^2 + e_1 y^2 + e_2 xy + e_3 x + e_4 y + e_5 = 0
 |
 |      or :math:`\vec{\epsilon} \in \mathbb{R}^5` where the leading coefficient is
 |      implicitly one
 |
 |      .. math::
 |
 |          x^2 + \epsilon_1 y^2 + \epsilon_2 xy + \epsilon_3 x + \epsilon_4 y + \epsilon_5 = 0
 |
 |      In this latter case, position, orientation and aspect ratio of the
 |      ellipse will be correct, but the overall scale of the ellipse is not
 |      determined.  To correct this, we can pass in a single point ``p`` that
 |      we know lies on the perimeter of the ellipse.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> Ellipse.Polynomial([0.625, 0.625, 0.75, -6.75, -7.25, 24.625])
 |
 |      :seealso: :meth:`polynomial`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  E
 |      Return ellipse matrix
 |
 |      :return: ellipse matrix
 |      :rtype: ndarray(2,2)
 |
 |      The symmetric matrix :math:`\mat{E} \in \mathbb{R}^{2\times 2}` determines the radii and
 |      the orientation of the ellipse
 |
 |      .. math::
 |
 |          (\vec{x} - \vec{x}_0)^{\top} \mat{E} \, (\vec{x} - \vec{x}_0) = 1
 |
 |      :seealso: :meth:`centre` :meth:`theta` :meth:`radii`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.E
 |
 |  area
 |      Area of ellipse
 |
 |      :return: area
 |      :rtype: float
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.area
 |
 |  centre
 |      Return ellipse centre
 |
 |      :return: centre of the ellipse
 |      :rtype: ndarray(2)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.centre
 |
 |      :seealso: :meth:`radii` :meth:`theta` :meth:`E`
 |
 |  polynomial
 |      Return ellipse as a polynomial
 |
 |      :return: polynomial
 |      :rtype: ndarray(6)
 |
 |      An ellipse can be described by :math:`\vec{e} \in \mathbb{R}^6` which are the
 |      coefficents of a quadratic in :math:`x` and :math:`y`
 |
 |      .. math::
 |
 |          e_0 x^2 + e_1 y^2 + e_2 xy + e_3 x + e_4 y + e_5 = 0
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.polynomial
 |
 |      :seealso: :meth:`Polynomial`
 |
 |  radii
 |      Return radii of the ellipse
 |
 |      :return: radii of the ellipse
 |      :rtype: ndarray(2)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.radii
 |
 |      :seealso: :meth:`centre` :meth:`theta` :meth:`E`
 |
 |  theta
 |      Return orientation of ellipse
 |
 |      :return: orientation in radians, in the interval [-pi, pi)
 |      :rtype: float
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Ellipse
 |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
 |          >>> e.theta
 |
 |      :seealso: :meth:`centre` :meth:`radii` :meth:`E`
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.InterpSplineSE3
Python Library Documentation: class InterpSplineSE3 in module spatialmath.spline

class InterpSplineSE3(SplineSE3)
 |  InterpSplineSE3(timepoints: List[float], control_poses: List[spatialmath.pose3d.SE3], *, normalize_time: bool = False, bc_type: str = 'not-a-knot') -> None
 |
 |  Class for an interpolated trajectory in SE3, as a function of time, through control_poses with a cubic spline.
 |
 |  A combination of scipy.interpolate.CubicSpline and scipy.spatial.transform.RotationSpline (itself also cubic)
 |  under the hood.
 |
 |  Method resolution order:
 |      InterpSplineSE3
 |      SplineSE3
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __call__(self, t: float) -> spatialmath.pose3d.SE3
 |      Compute function value at t.
 |      Return:
 |          pose: SE3
 |
 |  __init__(self, timepoints: List[float], control_poses: List[spatialmath.pose3d.SE3], *, normalize_time: bool = False, bc_type: str = 'not-a-knot') -> None
 |      Construct a InterpSplineSE3 object
 |
 |      Extends the scipy CubicSpline object
 |      https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicSpline.html#cubicspline
 |
 |      Args :
 |          timepoints : list of times corresponding to provided poses
 |          control_poses : list of SE3 objects that govern the shape of the spline.
 |          normalize_time : flag to map times into the range [0, 1]
 |          bc_type : boundary condition provided to scipy CubicSpline backend.
 |                    string options: ["not-a-knot" (default), "clamped", "natural", "periodic"].
 |                    For tuple options and details see the scipy docs link above.
 |
 |  derivative(self, t: float) -> spatialmath.twist.Twist3
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SplineSE3:
 |
 |  visualize(self, sample_times: List[float], input_trajectory: Optional[List[spatialmath.pose3d.SE3]] = None, pose_marker_length: float = 0.2, animate: bool = False, repeat: bool = True, ax: Optional[matplotlib.axes._axes.Axes] = None) -> None
 |      Displays an animation of the trajectory with the control poses against an optional input trajectory.
 |
 |      Args:
 |          sample_times: which times to sample the spline at and plot
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from SplineSE3:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Line2
Python Library Documentation: class Line2 in module spatialmath.geom2d

class Line2(builtins.object)
 |  Line2(line: 'ArrayLike3')
 |
 |  Class to represent 2D lines
 |
 |  The internal representation is in homogeneous format
 |
 |  .. math::
 |
 |          ax + by + c = 0
 |
 |  Methods defined here:
 |
 |  __init__(self, line: 'ArrayLike3')
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __str__(self) -> 'str'
 |      Return str(self).
 |
 |  contains(self, p: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
 |      Test if point is in line
 |
 |      :param p1: point to test
 |      :type p1: array_like(2) or array_like(3)
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: True if point lies in the line
 |      :rtype: bool
 |
 |  contains_polygon_point(self)
 |
 |  distance_line_line(self)
 |      # these should have same names as for 3d case
 |
 |  distance_line_point(self)
 |
 |  general(self) -> 'Tuple[float, float]'
 |      Parameters of general line
 |
 |      :return: parameters of general line (m, c)
 |      :rtype: ndarray(2)
 |
 |      Return the parameters of a general line :math:`y = mx + c`.
 |
 |  intersect(self, other: 'Line2', tol: 'float' = 20) -> 'R3'
 |      Intersection with line
 |
 |      :param other: another 2D line
 |      :type other: Line2
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: intersection point in homogeneous form
 |      :rtype: ndarray(3)
 |
 |      If the lines are parallel then the third element of the returned
 |      homogeneous point will be zero (an ideal point).
 |
 |  intersect_polygon___line(self)
 |
 |  intersect_segment(self, p1: 'ArrayLike2', p2: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
 |      Test for line intersecting line segment
 |
 |      :param p1: start of line segment
 |      :type p1: array_like(2) or array_like(3)
 |      :param p2: end of line segment
 |      :type p2: array_like(2) or array_like(3)
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: True if they intersect
 |      :rtype: bool
 |
 |      Tests whether the line intersects the line segment defined by endpoints
 |      ``p1`` and ``p2`` which are given in Euclidean or homogeneous form.
 |
 |  plot(self, **kwargs) -> 'None'
 |      Plot the line using matplotlib
 |
 |      :param kwargs: arguments passed to Matplotlib ``pyplot.plot``
 |
 |  points_join(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  General(m, c) -> 'Self'
 |      Create line from general line
 |
 |      :param m: line gradient
 |      :type m: float
 |      :param c: line intercept
 |      :type c: float
 |      :return: a 2D line
 |      :rtype: a Line2 instance
 |
 |      Creates a line from the parameters of the general line :math:`y = mx + c`.
 |
 |      .. note:: A vertical line cannot be represented.
 |
 |  Join(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
 |      Create 2D line from two points
 |
 |      :param p1: point on the line
 |      :type p1: array_like(2) or array_like(3)
 |      :param p2: another point on the line
 |      :type p2: array_like(2) or array_like(3)
 |
 |      The points can be given in Euclidean or homogeneous form.
 |
 |  TwoPoints(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Line3
Python Library Documentation: class Line3 in module spatialmath.geom3d

class Line3(spatialmath.baseposelist.BasePoseList)
 |  Line3(v=None, w=None, check=True)
 |
 |  Method resolution order:
 |      Line3
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __eq__(l1, l2: 'Line3') -> 'bool'
 |      Test if two lines are equivalent
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :return: lines are equivalent
 |      :rtype: bool
 |
 |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
 |      space.  Note that because of the over parameterization, lines can be
 |      equivalent even if their coordinate vectors are different.
 |
 |      .. note:: There is a hardwired tolerance of 10eps.
 |
 |      :seealso: :meth:`isequal` :meth:`__ne__`
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __init__(self, v=None, w=None, check=True)
 |      Create a Line3 object
 |
 |      :param v: Plucker coordinate vector, or Plucker moment vector
 |      :type v: array_like(6) or array_like(3)
 |      :param w: Plucker direction vector, optional
 |      :type w: array_like(3), optional
 |      :param check: check that the parameters are valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad arguments
 |      :return: 3D line
 |      :rtype: ``Line3`` instance
 |
 |      A representation of a 3D line using Plucker coordinates.
 |
 |      - ``Line3(p)`` creates a 3D line from a Plucker coordinate vector ``p=[v, w]``
 |         where ``v`` (3,) is the moment and ``w`` (3,) is the line direction.
 |
 |      - ``Line3(v, w)`` as above but the components ``v`` and ``w`` are
 |        provided separately.
 |
 |      - ``Line3(L)`` creates a copy of the ``Line3`` object ``L``.
 |
 |      :notes:
 |
 |          - The ``Line3`` object inherits from ``collections.UserList`` and has list-like
 |            behaviours.
 |          - A single ``Line3`` object contains a 1D-array of Plucker coordinates.
 |          - The elements of the array are guaranteed to be Plucker coordinates.
 |          - The number of elements is given by ``len(L)``
 |          - The elements can be accessed using index and slice notation, eg. ``L[1]`` or
 |            ``L[2:3]``
 |          - The ``Line3`` instance can be used as an iterator in a for loop or list comprehension.
 |          - Some methods support operations on the internal list.
 |
 |      :seealso: :meth:`Join` :meth:`TwoPlanes` :meth:`PointDir`
 |
 |  __mul__(left, right: 'Line3') -> 'float'
 |      Reciprocal product
 |
 |      :param left: Left operand
 |      :type left: Line3
 |      :param right: Right operand
 |      :type right: Line3
 |      :return: reciprocal product
 |      :rtype: float
 |
 |      ``left * right`` is the scalar reciprocal product :math:`\hat{w}_L \dot m_R + \hat{w}_R \dot m_R`.
 |
 |      .. note::
 |
 |          - Multiplication or composition of lines is not defined.
 |          - Pre-multiplication by an SE3 object is supported, see ``__rmul__``.
 |
 |      :seealso: :meth:`__rmul__`
 |
 |  __ne__(l1, l2: 'Line3') -> 'bool'
 |      Test if two lines are not equivalent
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :return: lines are not equivalent
 |      :rtype: bool
 |
 |      ``L1 != L2`` is True if the Line3 objects describe different lines in
 |      space.  Note that because of the over parameterization, lines can be
 |      equivalent even if their coordinate vectors are different.
 |
 |      .. note:: There is a hardwired tolerance of 10eps.
 |
 |      :seealso: :meth:`__ne__`
 |
 |  __or__(l1, l2: 'Line3') -> 'bool'
 |      Overloaded ``|`` operator tests for parallelism
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :return: lines are parallel
 |      :rtype: bool
 |
 |      ``l1 | l2`` is an operator which is true if the two lines are parallel.
 |
 |      .. note:: The ``|`` operator has low precendence.
 |
 |      .. note:: There is a hardwired tolerance of 10eps.
 |
 |      :seealso: :meth:`isparallel` :meth:`__xor__`
 |
 |  __repr__(self) -> 'str'
 |      Display Line3
 |
 |      :return: String representation of line parameters
 |      :rtype: str
 |
 |      Displays the line parameters in compact single line format.
 |
 |      For a multi-valued ``Line3``, one line per value in ``Line3``.
 |
 |  __rmul__(right, left: 'SE3') -> 'Line3'
 |      Rigid-body transformation of 3D line
 |
 |      :param left: Rigid-body transform
 |      :type left: SE3
 |      :param right: 3D line
 |      :type right: Line
 |      :return: transformed 3D line
 |      :rtype: Line3 instance
 |
 |      ``T * line`` is the line transformed by the rigid body transformation ``T``.
 |
 |      :seealso: :meth:`__mul__`
 |
 |  __str__(self) -> 'str'
 |      Convert Line3 to a string
 |
 |      :return: String representation of line parameters
 |      :rtype: str
 |
 |      ``str(line)`` is a string showing Plucker parameters in a compact single
 |      line format like::
 |
 |          { 0 0 0; -1 -2 -3}
 |
 |      where the first three numbers are the moment, and the last three are the
 |      direction vector.
 |
 |      For a multi-valued ``Line3``, one line per value in ``Line3``.
 |
 |  __xor__(l1, l2: 'Line3') -> 'bool'
 |      Overloaded ``^`` operator tests for intersection
 |
 |      :param l2: Second line
 |      :type l2: Line3
 |      :return: lines intersect
 |      :rtype: bool
 |
 |      ``l1 ^ l2`` is an operator which is true if the two lines intersect.
 |
 |      .. note::
 |
 |          - The ``^`` operator has low precendence.
 |          - Is ``False`` if the lines are equivalent since they would intersect at
 |            an infinite number of points.
 |
 |      .. note:: There is a hardwired tolerance of 10eps.
 |
 |      :seealso: :meth:`intersects` :meth:`isparallel` :meth:`isintersecting`
 |
 |  append(self, x: 'Line3')
 |      Append a line
 |
 |      :param x: line object
 |      :type x: Line3
 |      :raises ValueError: Attempt to append a non Plucker object
 |      :return: Line3 object with new line appended
 |      :rtype: Line3 instance
 |
 |  closest_to_line(l1, l2: 'Line3') -> 'Tuple[Points3, Rn]'
 |      Closest point between lines
 |
 |      :param l2: second line
 |      :type l2: Line3
 |      :return: nearest points and distance between lines at those points
 |      :rtype: ndarray(3,N), ndarray(N)
 |
 |      There are four cases:
 |
 |      * ``len(self) == len(other) == 1`` find the point on the first line closest to the second line, as well
 |        as the minimum distance between the lines.
 |      * ``len(self) == 1, len(other) == N`` find the point of intersection between the first
 |        line and the ``N`` other lines, returning ``N`` intersection points and distances.
 |      * ``len(self) == N, len(other) == 1`` find the point of intersection between the ``N`` first
 |        lines and the other line, returning ``N`` intersection points and distances.
 |      * ``len(self) == N, len(other) == M`` for each  of the ``N`` first
 |        lines find the closest intersection with each of the ``M`` other lines, returning ``N``
 |        intersection points and distances.
 |
 |      ** this last one should be an option, default behavior would be to
 |      test self[i] against line[i]
 |      ** maybe different function
 |
 |      For two sets of lines, of equal size, return an array of closest points
 |      and distances.
 |
 |      Example::
 |
 |          .. runblock:: pycon
 |
 |              >>> from spatialmath import Line3
 |              >>> line1 = Line3.Join([1, 1, 0], [1, 1, 1])
 |              >>> line2 = Line3.Join([0, 0, 0], [2, 3, 5])
 |              >>> line1.closest_to_line(line2)
 |
 |      :reference: `Plucker coordinates <https://web.cs.iastate.edu/~cs577/handouts/plucker-coordinates.pdf>`_
 |
 |
 |      :seealso: :meth:`distance`
 |
 |  closest_to_point(self, x: 'ArrayLike3') -> 'Tuple[R3, float]'
 |      Point on line closest to given point
 |
 |      :param x: An arbitrary 3D point
 |      :type x: array_like(3)
 |      :return: Point on the line and distance to line
 |      :rtype: ndarray(3), float
 |
 |      Find the point on the line closest to ``x`` as well as the distance
 |      at that closest point.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Line3
 |          >>> line1 = Line3.Join([0, 0, 0], [2, 2, 3])
 |          >>> line1.closest_to_point([1, 1, 1])
 |
 |      :seealso: meth:`point`
 |
 |  commonperp(l1, l2: 'Line3') -> 'Line3'
 |      Common perpendicular to two lines
 |
 |      :param l2: Second line
 |      :type l2: Line3
 |      :return: Perpendicular line
 |      :rtype: Line3 instance or None
 |
 |      ``l1.commonperp(l2)`` is the common perpendicular line between the two lines.
 |      Returns ``None`` if the lines are parallel.
 |
 |      :seealso: :meth:`intersect`
 |
 |  contains(self, x: 'Union[R3, Points3]', tol: 'float' = 20) -> 'Union[bool, List[bool]]'
 |      Test if points are on the line
 |
 |      :param x: 3D point
 |      :type x: 3-element array_like, or ndarray(3,N)
 |      :param tol: Tolerance in units of eps, defaults to 20
 |      :type tol: float, optional
 |      :raises ValueError: Bad argument
 |      :return: Whether point is on the line
 |      :rtype: bool or numpy.ndarray(N) of bool
 |
 |      ``line.contains(X)`` is true if the point ``X`` lies on the line defined by
 |      the Line3 object self.
 |
 |      If ``X`` is an array with 3 rows, the test is performed on every column and
 |      an array of booleans is returned.
 |
 |  distance(l1, l2: 'Line3', tol: 'float' = 20) -> 'float'
 |      Minimum distance between lines
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :param tol: Tolerance in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: Closest distance between lines
 |      :rtype: float
 |
 |      ``l1.distance(l2) is the minimum distance between two lines.
 |
 |      .. note:: Works for parallel, skew and intersecting lines.
 |
 |      :seealso: :meth:`closest_to_line`
 |
 |  intersect_plane(self, plane: 'Union[ArrayLike4, Plane3]', tol: 'float' = 20) -> 'Tuple[R3, float]'
 |      Line intersection with a plane
 |
 |      :param plane: A plane
 |      :type plane: array_like(4) or Plane3
 |      :param tol: Tolerance in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: Intersection point, λ
 |      :rtype: ndarray(3), float
 |
 |      - ``P, λ = line.intersect_plane(plane)`` is the point where the line
 |        intersects the plane, and the corresponding λ value.
 |        Return None, None if no intersection.
 |
 |      The plane can be specified as:
 |
 |       - a 4-vector :math:`[a, b, c, d]` which describes the plane :math:`\pi: ax + by + cz + d=0`.
 |       - a ``Plane`` object
 |
 |       The return value is a named tuple with elements:
 |
 |          - ``.p`` for the point on the line as a numpy.ndarray, shape=(3,)
 |          - ``.lam`` the `lambda` value for the point on the line.
 |
 |      :sealso: :meth:`point` :class:`Plane`
 |
 |  intersect_volume(self, bounds: 'ArrayLike6') -> 'Tuple[Points3, Rn]'
 |      Line intersection with a volume
 |
 |      :param bounds: Bounds of an axis-aligned rectangular cuboid
 |      :type plane: array_like(6)
 |      :return: Intersection point, λ value
 |      :rtype: ndarray(3,N), ndarray(N)
 |
 |      ``P, λ = line.intersect_volume(bounds)`` is a matrix (3xN) with columns
 |      that indicate where the line intersects the faces of the volume and
 |      the corresponding λ values.
 |
 |      The volume is specified by ``bounds`` = [xmin xmax ymin ymax zmin zmax].
 |
 |      The number of
 |      columns N is either:
 |
 |      - 0, when the line is outside the plot volume or,
 |      - 2 when the line pierces the bounding volume.
 |
 |
 |      See also :meth:`plot` :meth:`point`
 |
 |  intersects(l1, l2: 'Line3') -> 'Union[R3, None]'
 |      Intersection point of two lines
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :return: 3D intersection point
 |      :rtype: ndarray(3) or None
 |
 |      ``l1.intersects(l2)`` is the point of intersection of the two lines, or
 |      ``None`` if the lines do not intersect or are equivalent.
 |
 |      :seealso: :meth:`commonperp :meth:`eq` :meth:`__xor__`
 |
 |  isequal(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
 |      Test if two lines are equivalent
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :param tol: Tolerance in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: lines are equivalent
 |      :rtype: bool
 |
 |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
 |      space.  Note that because of the over parameterization, lines can be
 |      equivalent even if their coordinate vectors are different.
 |
 |      :seealso: :meth:`__eq__`
 |
 |  isintersecting(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
 |      Test if lines are intersecting
 |
 |      :param l2: Second line
 |      :type l2: Line3
 |      :param tol: Tolerance in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: lines intersect
 |      :rtype: bool
 |
 |      ``l1.isintersecting(l2)`` is true if the two lines intersect.
 |
 |      .. note:: Is ``False`` if the lines are equivalent since they would intersect at
 |            an infinite number of points.
 |
 |      :seealso: :meth:`__xor__` :meth:`intersects` :meth:`isparallel`
 |
 |  isparallel(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
 |      Test if lines are parallel
 |
 |      :param l2: Second line
 |      :type l2: ``Line3``
 |      :param tol: Tolerance in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: lines are parallel
 |      :rtype: bool
 |
 |      ``l1.isparallel(l2)`` is true if the two lines are parallel.
 |
 |      ``l1 | l2`` as above but in binary operator form
 |
 |      :seealso: :meth:`__or__` :meth:`intersects`
 |
 |  lam(self, point: 'ArrayLike3') -> 'float'
 |      Parametric distance from principal point
 |
 |      :param point: 3D point
 |      :type point: array_like(3)
 |      :return: parametric distance λ
 |      :rtype: float
 |
 |      ``line.lam(P)`` is the value of :math:`\lambda` such that
 |      :math:`Q = P_p + \lambda \hat{d}` is closest to ``P``.
 |
 |      :seealso: :meth:`point`
 |
 |  plot(self, *pos, bounds: 'Optional[ArrayLike]' = None, ax: 'Optional[plt.Axes]' = None, **kwargs) -> 'List[plt.Artist]'
 |       Plot a line
 |
 |      :param bounds: Bounds of an axis-aligned rectangular cuboid as [xmin xmax ymin ymax zmin zmax], optional
 |      :type plane: 6-element array_like
 |      :param **kwargs: Extra arguents passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
 |      :return: Plotted line
 |      :rtype: Matplotlib artists
 |
 |      - ``line.plot(bounds)`` adds a line segment to the current axes, and the handle of the line is returned.
 |        The line segment is defined by the intersection of the line and the given rectangular cuboid.
 |        If the line does not intersect the plotting volume None is returned.
 |
 |      - ``line.plot()`` as above but the bounds are taken from the axis limits of the current axes.
 |
 |      The line color or style is specified by:
 |
 |          - a  MATLAB-style linestyle like 'k--'
 |          - additional arguments passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
 |
 |      :seealso: :meth:`intersect_volume`
 |
 |  point(self, lam: 'Union[float, ArrayLike]') -> 'Points3'
 |      Generate point on line
 |
 |      :param lam: Scalar distance from principal point
 |      :type lam: float
 |      :return: Distance from principal point to the origin
 |      :rtype: float
 |
 |      ``line.point(λ)`` is a point on the line, where ``λ`` is the parametric
 |      distance along the line from the principal point of the line such
 |      that :math:`P = P_p + \lambda \hat{d}` and :math:`\hat{d}` is the line
 |      direction given by ``line.uw``.
 |
 |      :seealso: :meth:`pp` :meth:`closest` :meth:`uw` :meth:`lam`
 |
 |  side(self, other: 'Line3') -> 'float'
 |      Plucker side operator
 |
 |      :param other: second line
 |      :type other: Line3
 |      :return: permuted dot product
 |      :rtype: float
 |
 |      This permuted dot product operator is zero whenever the lines intersect or are parallel.
 |
 |  skew(self) -> 'R4x4'
 |      Line as a Plucker skew-symmetric matrix
 |
 |      :return: Skew-symmetric matrix form of Plucker coordinates
 |      :rtype: ndarray(4,4)
 |
 |      ``line.skew()`` is the Plucker matrix, a 4x4 skew-symmetric matrix
 |      representation of the line whose six unique elements are the
 |      Plucker coordinates of the line.
 |
 |      .. math::
 |
 |          \sk{L} = \begin{bmatrix} 0 & v_z & -v_y & \omega_x \\
 |              -v_z & 0 & v_x & \omega_y \\
 |              v_y & -v_x & 0 & \omega_z \\
 |              -\omega_x & -\omega_y & -\omega_z & 0 \end{bmatrix}
 |
 |      .. note::
 |
 |          - For two homogeneous points P and Q on the line, :math:`PQ^T-QP^T` is
 |          also skew symmetric.
 |          - The projection of Plucker line by a perspective camera is a
 |          homogeneous line (3x1) given by :math:`\vee C M C^T` where :math:`C
 |          \in \mathbf{R}^{3 \times 4}` is the camera matrix.
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  IntersectingPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
 |
 |  Join(P: 'ArrayLike3', Q: 'ArrayLike3') -> 'Self'
 |      Create 3D line from two 3D points
 |
 |      :param P: First 3D point
 |      :type P: array_like(3)
 |      :param Q: Second 3D point
 |      :type Q: array_like(3)
 |      :return: 3D line
 |      :rtype: ``Line3`` instance
 |
 |      ``Line3.Join(P, Q)`` create a ``Line3`` object that represents
 |      the line joining the 3D points ``P`` (3,) and ``Q`` (3,). The direction
 |      is from ``Q`` to ``P``.
 |
 |      :seealso: :meth:`IntersectingPlanes` :meth:`PointDir`
 |
 |  PointDir(point: 'ArrayLike3', dir: 'ArrayLike3') -> 'Self'
 |      Create 3D line from a point and direction
 |
 |      :param point: A 3D point
 |      :type point: array_like(3)
 |      :param dir: Direction vector
 |      :type dir: array_like(3)
 |      :return: 3D line
 |      :rtype: ``Line3`` instance
 |
 |      ``Line3.PointDir(P, W)`` is a `Line3`` object that represents the
 |      line containing the point ``P`` and parallel to the direction vector ``W``.
 |
 |      :seealso: :meth:`Join` :meth:`IntersectingPlanes`
 |
 |  TwoPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
 |      Create 3D line from intersection of two planes
 |
 |      :param pi1: First plane
 |      :type pi1: array_like(4), or ``Plane``
 |      :param pi2: Second plane
 |      :type pi2: array_like(4), or ``Plane``
 |      :return: 3D line
 |      :rtype: ``Line3`` instance
 |
 |      ``L = Line3.TwoPlanes(π1, π2)`` is a ``Line3`` object that represents
 |      the line formed by the intersection of two planes ``π1`` and ``π3``.
 |
 |      Planes are represented by the 4-vector :math:`[a, b, c, d]` which describes
 |      the plane :math:`\pi: ax + by + cz + d=0`.
 |
 |      :seealso: :meth:`Join` :meth:`PointDir`
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x: 'NDArray', check: 'bool' = False) -> 'bool'
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  pp
 |      Principal point of the 3D line
 |
 |      :return: Principal point of the line
 |      :rtype: ndarray(3)
 |
 |      ``line.pp`` is the point on the line that is closest to the origin.
 |
 |      Notes:
 |
 |       - Same as Plucker.point(0)
 |
 |      :seealso: :meth:`ppd` :meth`point`
 |
 |  ppd
 |      Distance from principal point to the origin
 |
 |      :return: Distance from principal point to the origin
 |      :rtype: float
 |
 |      ``line.ppd`` is the distance from the principal point to the origin.
 |      This is the smallest distance of any point on the line
 |      to the origin.
 |
 |      :seealso: :meth:`pp`
 |
 |  shape
 |
 |  uw
 |      Line direction as a unit vector
 |
 |      :return: Line direction as a unit vector
 |      :rtype: ndarray(3,)
 |
 |      ``line.uw`` is a unit-vector parallel to the line.
 |
 |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
 |
 |      :seealso: :meth:`w`
 |
 |  v
 |      Moment vector
 |
 |      :return: the moment vector
 |      :rtype: ndarray(3)
 |
 |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
 |
 |      :seealso: :meth:`w`
 |
 |  vec
 |      Line as a Plucker coordinate vector
 |
 |      :return: Plucker coordinate vector
 |      :rtype: ndarray(6,)
 |
 |      ``line.vec`` is the  Plucker coordinate vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
 |
 |  w
 |      Direction vector
 |
 |      :return: the direction vector
 |      :rtype: ndarray(3)
 |
 |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
 |
 |      :seealso: :meth:`v` :meth:`uw`
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __add__(self, other)
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.LineSegment2
Python Library Documentation: class LineSegment2 in module spatialmath.geom2d

class LineSegment2(Line2)
 |  LineSegment2(line: 'ArrayLike3')
 |
 |  Method resolution order:
 |      LineSegment2
 |      Line2
 |      builtins.object
 |
 |  Methods inherited from Line2:
 |
 |  __init__(self, line: 'ArrayLike3')
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __str__(self) -> 'str'
 |      Return str(self).
 |
 |  contains(self, p: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
 |      Test if point is in line
 |
 |      :param p1: point to test
 |      :type p1: array_like(2) or array_like(3)
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: True if point lies in the line
 |      :rtype: bool
 |
 |  contains_polygon_point(self)
 |
 |  distance_line_line(self)
 |      # these should have same names as for 3d case
 |
 |  distance_line_point(self)
 |
 |  general(self) -> 'Tuple[float, float]'
 |      Parameters of general line
 |
 |      :return: parameters of general line (m, c)
 |      :rtype: ndarray(2)
 |
 |      Return the parameters of a general line :math:`y = mx + c`.
 |
 |  intersect(self, other: 'Line2', tol: 'float' = 20) -> 'R3'
 |      Intersection with line
 |
 |      :param other: another 2D line
 |      :type other: Line2
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: intersection point in homogeneous form
 |      :rtype: ndarray(3)
 |
 |      If the lines are parallel then the third element of the returned
 |      homogeneous point will be zero (an ideal point).
 |
 |  intersect_polygon___line(self)
 |
 |  intersect_segment(self, p1: 'ArrayLike2', p2: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
 |      Test for line intersecting line segment
 |
 |      :param p1: start of line segment
 |      :type p1: array_like(2) or array_like(3)
 |      :param p2: end of line segment
 |      :type p2: array_like(2) or array_like(3)
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: True if they intersect
 |      :rtype: bool
 |
 |      Tests whether the line intersects the line segment defined by endpoints
 |      ``p1`` and ``p2`` which are given in Euclidean or homogeneous form.
 |
 |  plot(self, **kwargs) -> 'None'
 |      Plot the line using matplotlib
 |
 |      :param kwargs: arguments passed to Matplotlib ``pyplot.plot``
 |
 |  points_join(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from Line2:
 |
 |  General(m, c) -> 'Self'
 |      Create line from general line
 |
 |      :param m: line gradient
 |      :type m: float
 |      :param c: line intercept
 |      :type c: float
 |      :return: a 2D line
 |      :rtype: a Line2 instance
 |
 |      Creates a line from the parameters of the general line :math:`y = mx + c`.
 |
 |      .. note:: A vertical line cannot be represented.
 |
 |  Join(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
 |      Create 2D line from two points
 |
 |      :param p1: point on the line
 |      :type p1: array_like(2) or array_like(3)
 |      :param p2: another point on the line
 |      :type p2: array_like(2) or array_like(3)
 |
 |      The points can be given in Euclidean or homogeneous form.
 |
 |  TwoPoints(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from Line2:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Plane3
Python Library Documentation: class Plane3 in module spatialmath.geom3d

class Plane3(builtins.object)
 |  Plane3(c: 'ArrayLike4')
 |
 |  Create a plane object from linear coefficients
 |
 |  :param c: Plane coefficients
 |  :type c: array_like(4)
 |  :return: a Plane object
 |  :rtype: Plane
 |
 |  Planes are represented by the 4-vector :math:`[a, b, c, d]` which describes
 |  the plane :math:`\pi: ax + by + cz + d=0`.
 |
 |  Methods defined here:
 |
 |  __init__(self, c: 'ArrayLike4')
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  __repr__(self) -> 'str'
 |      Display parameters of plane
 |
 |      :return: Compact string representation of plane
 |      :rtype: str
 |
 |  __str__(self) -> 'str'
 |      Convert plane to string representation
 |
 |      :return: Compact string representation of plane
 |      :rtype: str
 |
 |  contains(self, p: 'ArrayLike3', tol: 'float' = 20) -> 'bool'
 |      Test if point in plane
 |
 |      :param p: A 3D point
 |      :type p: array_like(3)
 |      :param tol: tolerance in units of eps, defaults to 20
 |      :type tol: float
 |      :return: if the point is in the plane
 |      :rtype: bool
 |
 |  plot(self, bounds: 'Optional[ArrayLike]' = None, ax: 'Optional[plt.Axes]' = None, **kwargs)
 |      Plot plane
 |
 |      :param bounds: bounds of plot volume, defaults to None
 |      :type bounds: array_like(2|4|6), optional
 |      :param ax: 3D axes to plot into, defaults to None
 |      :type ax: Axes, optional
 |      :param kwargs: optional arguments passed to ``plot_surface``
 |
 |      The ``bounds`` of the 3D plot volume is [xmin, xmax, ymin, ymax, zmin, zmax]
 |      and a 3D plot is created if not already existing.  If ``bounds`` is not
 |      provided it is taken from current 3D axes.
 |
 |      The plane is drawn using ``plot_surface``.
 |
 |      :seealso: :func:`axes_logic`
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  LinePoint(l: 'Line3', p: 'ArrayLike3') -> 'Self'
 |      Create a plane object from a line and point
 |
 |      :param l: 3D line
 |      :type l: Line3
 |      :param p: Points in the plane
 |      :type p: ndarray(3)
 |      :return: a Plane object
 |      :rtype: Plane
 |
 |      :seealso: :meth:`PointNormal`  :meth:`ThreePoints`
 |
 |  PointNormal(p: 'ArrayLike3', n: 'ArrayLike3') -> 'Self'
 |      Create a plane object from point and normal
 |
 |      :param p: Point in the plane
 |      :type p: array_like(3)
 |      :param n: Normal vector to the plane
 |      :type n: array_like(3)
 |      :return: a Plane object
 |      :rtype: Plane
 |
 |      :seealso: :meth:`ThreePoints` :meth:`LinePoint`
 |
 |  ThreePoints(p: 'R3x3') -> 'Self'
 |      Create a plane object from three points
 |
 |      :param p: Three points in the plane
 |      :type p: ndarray(3,3)
 |      :return: a Plane object
 |      :rtype: Plane
 |
 |      The points in ``p`` are arranged as columns.
 |
 |      :seealso: :meth:`PointNormal`  :meth:`LinePoint`
 |
 |  TwoLines(l1: 'Line3', l2: 'Line3') -> 'Self'
 |      Create a plane object from two line
 |
 |      :param l1: 3D line
 |      :type l1: Line3
 |      :param l2: 3D line
 |      :type l2: Line3
 |      :return: a Plane object
 |      :rtype: Plane
 |
 |      .. warning:: This algorithm fails if the lines are parallel.
 |
 |      :seealso: :meth:`LinePoint` :meth:`PointNormal`  :meth:`ThreePoints`
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  intersection(pi1: 'Plane3', pi2: 'Plane3', pi3: 'Plane3') -> 'R3'
 |      Intersection point of three planes
 |
 |      :param pi1: plane 1
 |      :type pi1: Plane
 |      :param pi2: plane 2
 |      :type pi2: Plane
 |      :param pi3: plane 3
 |      :type pi3: Plane
 |      :return: coordinates of intersection point
 |      :rtype: ndarray(3)
 |
 |      This static method computes the intersection point of the three planes
 |      given as arguments.
 |
 |      .. warning:: This algorithm fails if the planes do not intersect, or
 |          intersect along a line.
 |
 |      :seealso: :meth:`Plane`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  d
 |      Plane offset
 |
 |      :return: Offset of the plane
 |      :rtype: float
 |
 |      For a plane :math:`\pi: ax + by + cz + d=0` this is the scalar
 |      :math:`d`.
 |
 |
 |      :seealso: :meth:`n`
 |
 |  n
 |      Normal to the plane
 |
 |      :return: Normal to the plane
 |      :rtype: ndarray(3)
 |
 |      For a plane :math:`\pi: ax + by + cz + d=0` this is the vector
 |      :math:`[a,b,c]`.
 |
 |      :seealso: :meth:`d`
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Polygon2
Python Library Documentation: class Polygon2 in module spatialmath.geom2d

class Polygon2(builtins.object)
 |  Polygon2(vertices: 'Optional[Points2]' = None, close: 'bool' = True)
 |
 |  Class to represent 2D (planar) polygons
 |
 |  .. note:: Uses Matplotlib primitives to perform transformations and
 |      intersections.
 |
 |  Methods defined here:
 |
 |  __init__(self, vertices: 'Optional[Points2]' = None, close: 'bool' = True)
 |      Create planar polygon from vertices
 |
 |      :param vertices: vertices of polygon, defaults to None
 |      :type vertices: ndarray(2, N), optional
 |      :param close: closes the polygon, replicates the first vertex, defaults to True
 |      :type closed: bool, optional
 |
 |      Create a polygon from a set of points provided as columns of the 2D
 |      array ``vertices``.
 |      A closed polygon is created so the last vertex should not equal the
 |      first.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |
 |      .. warning:: The points must be sequential around the perimeter and
 |          counter clockwise, otherwise moments will be negative.
 |
 |      .. note:: The polygon is represented by a Matplotlib ``Path``
 |
 |  __len__(self) -> 'int'
 |      Number of vertices in polygon
 |
 |      :return: number of vertices
 |      :rtype: int
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> len(p)
 |
 |  __repr__(self) -> 'str'
 |      Return repr(self).
 |
 |  __str__(self) -> 'str'
 |      Polygon to string
 |
 |      :return: brief summary of polygon
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> import numpy as np
 |          >>> p = Polygon2(np.array([[1, 3, 2], [2, 2, 4]]))
 |          >>> print(p)
 |
 |  animate(self, T, **kwargs) -> 'None'
 |      Animate a polygon
 |
 |      :param T: new pose of Polygon
 |      :type T: SE2
 |      :param kwargs: options passed to Matplotlib ``Patch``
 |
 |      The plotted polygon is moved to the pose given by ``T``. The pose is
 |      always with respect to the initial vertices when the polygon was
 |      constructed.  The vertices of the polygon will be updated to reflect
 |      what is plotted.
 |
 |      If the polygon has already plotted, it will keep the same graphical
 |      attributes.  If new attributes are given they will replace those
 |      given at construction time.
 |
 |      :seealso: :meth:`plot`
 |
 |  area(self) -> 'float'
 |      Area of polygon
 |
 |      :return: area
 |      :rtype: float
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.area()
 |
 |      :seealso: :meth:`moment`
 |
 |  bbox(self) -> 'R4'
 |      Bounding box of polygon
 |
 |      :return: bounding box as [xmin, xmax, ymin, ymax]
 |      :rtype: ndarray(4)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.bbox()
 |
 |  centroid(self) -> 'R2'
 |      Centroid of polygon
 |
 |      :return: centroid
 |      :rtype: ndarray(2)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.centroid()
 |
 |      :seealso: :meth:`moment`
 |
 |  contains(self, p: 'ArrayLike2', radius: 'float' = 0.0) -> 'Union[bool, List[bool]]'
 |      Test if point is inside polygon
 |
 |      :param p: point
 |      :type p: array_like(2)
 |      :param radius: Add an additional margin to the polygon boundary, defaults to 0.0
 |      :type radius: float, optional
 |      :return: True if point is contained by polygon
 |      :rtype: bool
 |
 |      ``radius`` can be used to inflate the polygon, or if negative, to
 |      deflated it.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.contains([0, 0])
 |          >>> p.contains([2, 3])
 |
 |      .. warning:: Returns True if the point is on the edge of the polygon
 |          but False if the point is one of the vertices.
 |
 |      .. warning:: For a polygon with clockwise ordering of vertices the
 |          sign of ``radius`` is flipped.
 |
 |      :seealso: :func:`matplotlib.contains_point`
 |
 |  edges(self) -> 'Iterator'
 |      Iterate over polygon edge segments
 |
 |      Creates an iterator that returns pairs of points representing the
 |      end points of each segment.
 |
 |  intersects(self, other: 'Union[Polygon2, Line2, List[Polygon2], List[Line2]]') -> 'bool'
 |      Test for intersection
 |
 |      :param other: object to test for intersection
 |      :type other: Polygon2 or Line2 or list(Polygon2) or list(Line2)
 |      :return: True if the polygon intersects ``other``
 |      :rtype: bool
 |      :raises ValueError:
 |
 |      Returns true if the polygon intersects the the given polygon or 2D
 |      line. If ``other`` is a list, test against all in the list and return on the
 |      first intersection.
 |
 |  moment(self, p: 'int', q: 'int') -> 'float'
 |      Moments of polygon
 |
 |      :param p: moment order x
 |      :type p: int
 |      :param q: moment order y
 |      :type q: int
 |
 |      Returns the pq'th moment of the polygon
 |
 |      .. math::
 |
 |          M(p, q) = \sum_{i=0}^{n-1} x_i^p y_i^q
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.moment(0, 0)  # area
 |          >>> p.moment(3, 0)
 |
 |      Note is negative for clockwise perimeter.
 |
 |  plot(self, ax: 'Optional[plt.Axes]' = None, **kwargs) -> 'None'
 |      Plot polygon
 |
 |      :param ax: axes in which to draw the polygon, defaults to None
 |      :type ax: Axes, optional
 |      :param kwargs: options passed to Matplotlib ``Patch``
 |
 |      A Matplotlib Patch is created with the passed options ``**kwargs`` and
 |      added to the axes.
 |
 |      Examples::
 |
 |          >>> from spatialmath.base import plotvol2, plot_polygon
 |          >>> plotvol2(5)
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.plot(fill=False)
 |          >>> p.plot(facecolor="g", edgecolor="none")  # green filled triangle
 |
 |      .. plot::
 |
 |          from spatialmath import Polygon2
 |          from spatialmath.base import plotvol2
 |          p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          plotvol2(5)
 |          p.plot(fill=False)
 |
 |      .. plot::
 |
 |          from spatialmath import Polygon2
 |          from spatialmath.base import plotvol2
 |          p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          plotvol2(5)
 |          p.plot(facecolor="g", edgecolor="none")  # green filled triangle
 |
 |
 |      :seealso: :meth:`animate` :func:`matplotlib.PathPatch`
 |
 |  radius(self) -> 'float'
 |      Radius of smallest enclosing circle
 |
 |      :return: radius
 |      :rtype: float
 |
 |      This is the radius of the smalleset circle, centred at the centroid,
 |      that encloses all vertices.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.radius()
 |
 |  transformed(self, T: 'SE2') -> 'Self'
 |      A transformed copy of polygon
 |
 |      :param T: planar transformation
 |      :type T: SE2
 |      :return: transformed polygon
 |      :rtype: Polygon2
 |
 |      Returns a new polgyon whose vertices have been transformed by ``T``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2, SE2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.vertices()
 |          >>> p.transformed(SE2(10, 0, 0)).vertices() # shift by x+10
 |
 |  vertices(self, unique: 'bool' = True) -> 'Points2'
 |      Vertices of polygon
 |
 |      :param unique: return only the unique vertices , defaults to True
 |      :type unique: bool, optional
 |      :return: vertices
 |      :rtype: ndarray(2,n)
 |
 |      Returns the set of vertices.  The polygon is always closed, that is, the first
 |      and last vertices are the same.  The ``unique`` option does not include the last
 |      vertex.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Polygon2
 |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
 |          >>> p.vertices()
 |          >>> p.vertices(closed=True)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Quaternion
Python Library Documentation: class Quaternion in module spatialmath.quaternion

class Quaternion(spatialmath.baseposelist.BasePoseList)
 |  Quaternion(s: 'Any' = None, v=None, check: 'Optional[bool]' = True)
 |
 |  Quaternion class
 |
 |  A quaternion can be considered an ordered pair :math:`(s, \vec{v})`
 |  where :math:`s \in \mathbb{R}` is the *scalar* part and :math:`\vec{v} = (v_x, v_y, v_z) \in \mathbb{R}^3`
 |  is the *vector* part and is often written as
 |
 |  .. math:: \q = s \langle v_x, v_y, v_z \rangle
 |
 |  .. inheritance-diagram:: spatialmath.quaternion.Quaternion
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  Method resolution order:
 |      Quaternion
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __add__(left, right: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``+`` operator
 |
 |      :return: sum
 |      :rtype: Quaternion, UnitQuaternion
 |      :raises: ValueError
 |
 |      ==============   ==============   ==============  ===================
 |                 Operands                            Sum
 |      -------------------------------   -----------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ===================
 |      Quaternion       Quaternion       Quaternion      elementwise sum
 |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
 |      Quaternion       scalar           Quaternion      add to each element
 |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
 |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
 |      UnitQuaternion   scalar           Quaternion      add to each element
 |      ==============   ==============   ==============  ===================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``sum = left + right``
 |       1      N       N    ``sum[i] = left + right[i]``
 |       N      1       N    ``sum[i] = left[i] + right``
 |       N      N       N    ``sum[i] = left[i] + right[i]``
 |       N      M       -    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      A scalar of length N is a list, tuple or numpy array.
 |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]) + Quaternion([5,6,7,8])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([1,2,3,4])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  __eq__(left, right: 'Quaternion') -> 'bool'
 |      Overloaded ``==`` operator
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |      ``q1 == q2`` is True if ``q1` is elementwise equal to ``q2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q1 = Quaternion([1,2,3,4])
 |          >>> q2 = Quaternion([5,6,7,8])
 |          >>> q1 == q1
 |          >>> q1 == q2
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == q1
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == q2
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
 |
 |  __imul__(left, right: 'Quaternion') -> 'bool'
 |      Overloaded ``*=`` operator
 |
 |      :return: product
 |      :rtype: Quaternion
 |      :raises: ValueError
 |
 |      ``q1 *= q2`` sets ``q1 := q1 * q2``
 |      ``q1 *= s`` sets ``q1 := q1 * s`` where ``s`` is a scalar
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> q *= Quaternion([5,6,7,8])
 |          >>> print(q)
 |          >>> q *= 2
 |          >>> print(q)
 |
 |      :seealso: :func:`__mul__`
 |
 |  __init__(self, s: 'Any' = None, v=None, check: 'Optional[bool]' = True)
 |      Construct a new quaternion
 |
 |      :param s: scalar part
 |      :type s: float or ndarray(N)
 |      :param v: vector part
 |      :type v: ndarray(3), ndarray(Nx3)
 |
 |      - ``Quaternion()`` constructs a zero quaternion
 |      - ``Quaternion(s, v)`` construct a new quaternion from the scalar ``s``
 |        and the vector ``v``
 |      - ``Quaternion(q)`` construct a new quaternion from the 4-vector
 |        ``q = [s, v]``
 |      - ``Quaternion([q1, q2 .. qN])`` construct a new quaternion with ``N``
 |        values where each element is a 4-vector
 |      - ``Quaternion([Q1, Q2 .. QN])`` construct a new quaternion with ``N``
 |        values where each element is a Quaternion instance
 |      - ``Quaternion(M)`` construct a new quaternion with ``N`` values where
 |        ``Q`` is a 4xN NumPy array.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion()
 |          >>> Quaternion(1, [2,3,4])
 |          >>> Quaternion([1,2,3,4])
 |          >>> q=Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |          >>> len(q)
 |          >>> print(q)
 |
 |  __ipow__(self, n: 'int') -> 'Quaternion'
 |      Overloaded ``=**`` operator
 |
 |      :rtype: Quaternion instance
 |
 |      ``q **= N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
 |      an integer.  If ``N``<0 the result is conjugated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> q **= 2
 |          >>> q
 |          >>> q = Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |          >>> q **= 2
 |          >>> q
 |
 |
 |      :seealso: :func:`__pow__`
 |
 |  __mul__(left, right: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``*`` operator
 |
 |      :return: product
 |      :rtype: Quaternion
 |      :raises: ValueError
 |
 |      - ``q1 * q2`` is the Hamilton product of two quaternions
 |      - ``q * s`` is the scalar product, where ``s`` is a scalar
 |
 |      ==============   ==============   ==============  ================
 |                 Multiplicands                   Product
 |      -------------------------------   --------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ================
 |      Quaternion       Quaternion       Quaternion      Hamilton product
 |      Quaternion       UnitQuaternion   Quaternion      Hamilton product
 |      Quaternion       scalar           Quaternion      scalar product
 |      ==============   ==============   ==============  ================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``prod = left * right``
 |       1      N       N    ``prod[i] = left * right[i]``
 |       N      1       N    ``prod[i] = left[i] * right``
 |       N      N       N    ``prod[i] = left[i] * right[i]``
 |       N      M       -    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])
 |          >>> Quaternion([1,2,3,4]) * 2
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * 2
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * Quaternion([1,2,3,4])
 |          >>> Quaternion([1,2,3,4]) * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |      :seealso: :func:`__rmul__` :func:`__imul__` :func:`~spatialmath.base.quaternions.qqmul`
 |
 |  __ne__(left, right: 'Quaternion') -> 'bool'
 |      Overloaded ``!=`` operator
 |
 |      :rtype: bool
 |
 |      ``q1 != q2`` is True if ``q` is elementwise not equal to ``q2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q1 = Quaternion([1,2,3,4])
 |          >>> q2 = Quaternion([5,6,7,8])
 |          >>> q1 != q1
 |          >>> q1 != q2
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) != q1
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) != q2
 |
 |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
 |
 |  __neg__(self) -> 'Quaternion'
 |      Overloaded unary ``-`` operator
 |
 |      :rtype: Quaternion or UnitQuaternion
 |
 |      ``-q`` is a quaternion with all its components negated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> -Quaternion([1,2,3,4])
 |          >>> -Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  __pow__(self, n: 'int') -> 'Quaternion'
 |      Overloaded ``**`` operator
 |
 |      :rtype: Quaternion instance
 |
 |      ``q ** N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
 |      an integer.  If ``N``<0 the result is conjugated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion([1,2,3,4]) ** 2)
 |          >>> print(Quaternion([1,2,3,4]) ** -1)
 |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) ** 2)
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qpow`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> q
 |
 |  __rmul__(right, left: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``*`` operator
 |
 |      :return: product
 |      :rtype: Quaternion
 |      :raises: ValueError
 |
 |      ``s * q`` is the scalar product, where ``s`` is a scalar.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> 2 * Quaternion([1,2,3,4])
 |          >>> 2 * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |      :seealso: :func:`__mul__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of quaternion
 |
 |      :return: readable representation of quaternion
 |      :rtype: str
 |
 |      Format the quaternion elements into a single line format.  For example::
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> print(x)
 |          >> q = UnitQuaternion.Rx(0.3)
 |
 |      Note that unit quaternions are denoted by different delimiters for
 |      the vector part.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  __sub__(left, right: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``-`` operator
 |
 |      :return: difference
 |      :rtype: Quaternion, UnitQuaternion
 |      :raises: ValueError
 |
 |      ==============   ==============   ==============  ==========================
 |                 Operands                          Difference
 |      -------------------------------   ------------------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ==========================
 |      Quaternion       Quaternion       Quaternion      elementwise sum
 |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
 |      Quaternion       scalar           Quaternion      subtract from each element
 |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
 |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
 |      UnitQuaternion   scalar           Quaternion      subtract from each element
 |      ==============   ==============   ==============  ==========================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``diff = left - right``
 |       1      N       N    ``diff[i] = left - right[i]``
 |       N      1       N    ``diff[i] = left[i] - right``
 |       N      N       N    ``diff[i] = left[i] - right[i]``
 |       N      M       -    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      A scalar of length N is a list, tuple or numpy array.
 |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]) - Quaternion([5,6,7,8])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([1,2,3,4])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  __truediv__(self, other: 'Quaternion')
 |
 |  conj(self) -> 'Quaternion'
 |      Conjugate of quaternion
 |
 |      :rtype: Quaternion instance
 |
 |      ``q.conj()`` is the quaternion ``q`` with the vector part negated, ie.
 |      :math:`q = s \langle -v_x, -v_y, -v_z \rangle`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion.Pure([1,2,3]).conj())
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qconj`
 |
 |  exp(self, tol: 'float' = 20) -> 'Quaternion'
 |      Exponential of quaternion
 |
 |      :param tol: Tolerance when checking for pure quaternion, in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :rtype: Quaternion instance
 |
 |      ``q.exp()`` is the exponential of the quaternion ``q``, ie.
 |
 |      .. math::
 |
 |           e^s \cos \| v \|,  \langle e^s \frac{\vec{v}}{\| \vec{v} \|} \sin \| \vec{v} \| \rangle
 |
 |      For a pure quaternion with vector value :math:`\vec{v}` the the result
 |      is a unit quaternion equivalent to a rotation defined by
 |      :math:`2\vec{v}` intepretted as an Euler vector, that is, parallel to
 |      the axis of rotation and whose norm is the magnitude of rotation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> from math import pi
 |          >>> q = Quaternion([1, 2, 3, 4])
 |          >>> print(q.exp())
 |          >>> q = Quaternion.Pure([pi / 4, 0, 0])
 |          >>> print(q.exp())  # result is a UnitQuaternion
 |          >>> print(q.exp().angvec())
 |
 |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
 |
 |      :seealso: :meth:`Quaternion.log` :meth:`UnitQuaternion.log` :meth:`UnitQuaternion.AngVec` :meth:`UnitQuaternion.EulerVec`
 |
 |  inner(self, other) -> 'float'
 |      Inner product of quaternions
 |
 |      :rtype: float
 |
 |      ``q1.inner(q2)`` is the dot product of the equivalent vectors,
 |      ie. ``numpy.dot(q1.vec, q2.vec)``.
 |      The value of ``q.inner(q)`` is the same as ``q.norm ** 2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).inner(Quaternion([5,6,7,8]))
 |          >>> numpy.dot([1,2,3,4], [5,6,7,8])
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qinner`
 |
 |  log(self) -> 'Quaternion'
 |      Logarithm of quaternion
 |
 |      :rtype: Quaternion instance
 |
 |      ``q.log()`` is the logarithm of the quaternion ``q``, ie.
 |
 |      .. math::
 |
 |           \ln \| q \|,  \langle \frac{\vec{v}}{\| \vec{v} \|} \cos^{-1} \frac{s}{\| q \|} \rangle
 |
 |      For a ``UnitQuaternion`` the logarithm is a pure quaternion whose vector
 |      part :math:`\vec{v}` and :math:`\vec{v}/2` is a Euler vector: parallel
 |      to the axis of rotation and whose norm is the magnitude of rotation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion, UnitQuaternion
 |          >>> from math import pi
 |          >>> q = Quaternion([1, 2, 3, 4])
 |          >>> print(q.log())
 |          >>> q = UnitQuaternion.Rx(pi / 2)
 |          >>> print(q.log())
 |
 |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
 |
 |      :seealso: :meth:`Quaternion.exp` :meth:`Quaternion.log` :meth:`UnitQuaternion.angvec`
 |
 |  norm(self) -> 'float'
 |      Norm of quaternion
 |
 |      :rtype: float
 |
 |      ``q.norm()`` is the norm or length of the quaternion
 |      :math:`\sqrt{s^2 + v_x^2 + v_y^2 + v_z^2}`
 |
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).norm()
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).norm()
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  unit(self) -> 'UnitQuaternion'
 |      Unit quaternion
 |
 |      :rtype: UnitQuaternion instance
 |
 |      ``q.unit()`` is the quaternion ``q`` normalized to have a unit length.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> print(q)
 |          >>> print(q.unit())
 |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).unit())
 |
 |      Note that the return type is different, a ``UnitQuaternion``, which is
 |      distinguished by the use of double angle brackets to delimit the
 |      vector part.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  Pure(v: 'ArrayLike3') -> 'Quaternion'
 |      Construct a pure quaternion from a vector
 |
 |      :param v: vector
 |      :type v: 3-element array_like
 |
 |      ``Quaternion.Pure(v)`` is a Quaternion with a zero scalar part and the
 |      vector part set to ``v``,
 |      ie. :math:`q = 0 \langle v_x, v_y, v_z \rangle`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion.Pure([1,2,3]))
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x: 'ArrayLike4') -> 'bool'
 |      Test if vector is valid quaternion
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: explicitly check vector is unit length [default True]
 |      :type check: bool
 |      :return: True if the matrix has shape (4,).
 |      :rtype: bool
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> import numpy as np
 |          >>> Quaternion.isvalid(np.r_[1, 0, 0, 0])
 |          >>> Quaternion.isvalid(np.r_[1, 2, 3, 4])
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  matrix
 |      Matrix equivalent of quaternion
 |
 |      :rtype: Numpy array, shape=(4,4)
 |
 |      ``q.matrix`` is a 4x4 matrix which encodes the arithmetic rules of Hamilton multiplication.
 |      This matrix, multiplied by the 4-vector equivalent of a second quaternion, results in the 4-vector
 |      equivalent of the Hamilton product.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).matrix
 |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])   # Hamilton product
 |          >>> Quaternion([1,2,3,4]).matrix @ Quaternion([5,6,7,8]).vec  # matrix-vector product
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qmatrix`
 |
 |  s
 |      Scalar part of quaternion
 |
 |      :return: scalar part of quaternion
 |      :rtype: float or numpy.ndarray
 |
 |      ``q.s`` is the scalar part.  If `len(q)` is:
 |
 |          - 1, return a scalar float
 |          - N>1, return a NumPy array shape=(N,) is returned.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).s
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).s
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (4,)
 |      :rtype: tuple
 |
 |  v
 |      Vector part of quaternion
 |
 |      :return: vector part of quaternion
 |      :rtype: NumPy ndarray
 |
 |      ``q.v`` is the vector part.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(3,)
 |          - N>1, return a NumPy array shape=(N,3).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).v
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).v
 |
 |  vec
 |      Quaternion as a vector
 |
 |      :return: quaternion expressed as a 4-vector
 |      :rtype: numpy ndarray, shape=(4,)
 |
 |      ``q.vec`` is the quaternion as a vector.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(4,)
 |          - N>1, return a NumPy array shape=(N,4).
 |
 |      The quaternion coefficients are in the order (s, vx, vy, vz), ie. with
 |      the scalar (real part) first.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).vec
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec
 |
 |  vec_xyzs
 |      Quaternion as a vector
 |
 |      :return: quaternion expressed as a 4-vector
 |      :rtype: numpy ndarray, shape=(4,)
 |
 |      ``q.vec_xyzs`` is the quaternion as a vector.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(4,)
 |          - N>1, return a NumPy array shape=(N,4).
 |
 |      The quaternion coefficients are in the order (vx, vy, vz, s), ie. with
 |      the scalar (real part) last. This is useful when exporting to other
 |      packages like three.js or pybullet.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).vec_xyzs
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec_xyzs
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __iadd__(self, other)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SE2
Python Library Documentation: class SE2 in module spatialmath.pose2d

class SE2(SO2)
 |  SE2(x=None, y=None, theta=None, *, unit='rad', check=True)
 |
 |     SE(2) matrix class
 |
 |     This subclass represents rigid-body motion (pose) in 2D space.  Internally
 |     it is a 3x3 homogeneous transformation matrix belonging to the group SE(2).
 |
 |  .. inheritance-diagram:: spatialmath.pose2d.SE2
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  Method resolution order:
 |      SE2
 |      SO2
 |      spatialmath.baseposematrix.BasePoseMatrix
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  SE3(self, z=0)
 |      Create SE(3) from SE(2)
 |
 |      :param z: default z coordinate, defaults to 0
 |      :type z: float
 |      :return: SE(2) with same rotation but zero translation
 |      :rtype: SE2 instance
 |
 |      "Lifts" 2D rigid-body motion to 3D, rotation in the xy-plane (about the z-axis) and
 |      z-coordinate is settable.
 |
 |  Twist2(self)
 |
 |  __init__(self, x=None, y=None, theta=None, *, unit='rad', check=True)
 |      Construct new SE(2) object
 |
 |      :param unit: angular units 'deg' or 'rad' [default] if applicable
 |      :type unit: str, optional
 |      :param check: check for valid SE(2) elements if applicable, default to True
 |      :type check: bool
 |      :return: SE(2) matrix
 |      :rtype: SE2 instance
 |
 |      - ``SE2()`` is an SE2 instance representing a null motion -- the
 |        identity matrix
 |      - ``SE2(θ)`` is an SE2 instance representing a pure rotation of
 |        ``θ`` radians
 |      - ``SE2(θ, unit='deg')`` as above but ``θ`` in degrees
 |      - ``SE2(x, y)`` is an SE2 instance representing a pure translation of
 |        (``x``, ``y``)
 |      - ``SE2(t)`` is an SE2 instance representing a pure translation of
 |        (``x``, ``y``) where``t``=[x,y] is a 2-element array_like
 |      - ``SE2(x, y, θ)`` is an SE2 instance representing a translation of
 |        (``x``, ``y``) and a rotation of ``θ`` radians
 |      - ``SE2(x, y, θ, unit='deg')`` as above but ``θ`` in degrees
 |      - ``SE2(t)`` where ``t``=[x,y] is a 2-element array_like, is an SE2
 |        instance representing a pure translation of (``x``, ``y``)
 |      - ``SE2(q)`` where ``q``=[x,y,θ] is a 3-element array_like, is an SE2
 |        instance representing a translation of (``x``, ``y``) and a rotation
 |        of ``θ`` radians
 |      - ``SE2(t, unit='deg')`` as above but ``θ`` in degrees
 |      - ``SE2(T)`` is an SE2 instance with rigid-body motion described by the
 |        SE(2) matrix T which is a 3x3 numpy array.  If ``check`` is ``True``
 |        check the matrix belongs to SE(2).
 |      - ``SE2([T1, T2, ... TN])`` is an SE2 instance containing a sequence of
 |        N rigid-body motions, each described by an SE(2) matrix Ti which is a
 |        3x3 numpy array. If ``check`` is ``True`` then check each matrix
 |        belongs to SE(2).
 |      - ``SE2([X1, X2, ... XN])`` is an SE2 instance containing a sequence of
 |        N rigid-body motions, where each Xi is an SE2 instance.
 |
 |  inv(self)
 |      Inverse of SE(2)
 |
 |      :param self: pose
 |      :type self: SE2 instance
 |      :return: inverse
 |      :rtype: SE2
 |
 |      Notes:
 |
 |          - for elements of SE(2) this takes into account the matrix structure :math:`T = \left[ \begin{array}{cc} R & t \\ 0 & 1 \end{array} \right], T^{-1} = \left[ \begin{array}{cc} R^T & -R^T t \\ 0 & 1 \end{array} \right]`
 |          - if `x` contains a sequence, returns an `SE2` with a sequence of inverses
 |
 |  xyt(self)
 |      SE(2) as a configuration vector
 |
 |      :return: An array :math:`[x, y, \theta]` :rtype: numpy.ndarray
 |
 |      ``x.xyt`` is the rigidbody motion in minimal form as a translation and
 |      rotation expressed in vector form as :math:`[x, y, \theta]`.  If
 |      ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return an ndarray with shape=(N,3)
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  Exp(S, check=True)
 |      Construct a new SE(2) from se(2) Lie algebra
 |
 |      :param S: element of Lie algebra se(2)
 |      :type S: numpy ndarray
 |      :param check: check that passed matrix is valid se(2), default True
 |      :type check: bool
 |      :return: homogeneous transform matrix
 |      :rtype: SE2 instance
 |
 |      - ``SE2.Exp(S)`` is an SE(2) rotation defined by its Lie algebra
 |        which is a 3x3 se(2) matrix (skew symmetric)
 |      - ``SE2.Exp(t)`` is an SE(2) rotation defined by a 3-element twist
 |        vector array_like (the unique elements of the se(2) skew-symmetric matrix)
 |      - ``SE2.Exp(T)`` is a sequence of SE(2) rigid-body motions defined by an Nx3 matrix of twist vectors, one per row.
 |
 |      Note:
 |
 |      - an input 3x3 matrix is ambiguous, it could be the first or third case above. In this case the argument ``se2`` is the decider.
 |
 |      :seealso: :func:`spatialmath.base.transforms2d.trexp`, :func:`spatialmath.base.transformsNd.skew`
 |
 |  Rand(N=1, xrange=(-1, 1), yrange=(-1, 1), arange=(0, 6.283185307179586), unit='rad')
 |      Construct a new random SE(2)
 |
 |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
 |      :type xrange: 2-element sequence, optional
 |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
 |      :type yrange: 2-element sequence, optional
 |      :param arange: angle range [min,max], defaults to :math:`[0, 2\pi)`
 |      :type arange: 2-element sequence, optional
 |      :param N: number of random rotations, defaults to 1
 |      :type N: int
 |      :param unit: angular units 'deg' or 'rad' [default] if applicable
 |      :type unit: str, optional
 |      :return: homogeneous rigid-body transformation matrix
 |      :rtype: SE2 instance
 |
 |      Return an SE2 instance with random rotation and translation.
 |
 |      - ``SE2.Rand()`` is a random SE(2) rotation.
 |      - ``SE2.Rand(N)`` is an SE2 object containing a sequence of N random
 |        poses.
 |
 |      Example, create random ten vehicles in the xy-plane::
 |
 |          >>> x = SE3.Rand(N=10, xrange=[-2,2], yrange=[-2,2])
 |          >>> len(x)
 |          10
 |
 |  Rot(theta, unit='rad')
 |      Create an SE(2) rotation
 |
 |      :param theta: rotation angle in radians
 |      :type theta: float
 |      :param unit: angular units: "rad" [default] or "deg"
 |      :type unit: str
 |      :return: SE(2) matrix
 |      :rtype: SE2 instance
 |
 |      `SE2.Rot(theta)` is an SE(2) rotation of ``theta``
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> SE2.Rot(0.3)
 |          >>> SE2.Rot([0.2, 0.3])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Tx(x)
 |      Create an SE(2) translation along the X-axis
 |
 |      :param x: translation distance along the X-axis
 |      :type x: float
 |      :return: SE(2) matrix
 |      :rtype: SE2 instance
 |
 |      `SE2.Tx(x)` is an SE(2) translation of ``x`` along the x-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> SE2.Tx(2)
 |          >>> SE2.Tx([2,3])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Ty(y)
 |      Create an SE(2) translation along the Y-axis
 |
 |      :param y: translation distance along the Y-axis
 |      :type y: float
 |      :return: SE(2) matrix
 |      :rtype: SE2 instance
 |
 |      `SE2.Ty(y) is an SE(2) translation of ``y`` along the y-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> SE2.Ty(2)
 |          >>> SE2.Ty([2,3])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x, check=True)
 |      Test if matrix is valid SE(2)
 |
 |      :param x: matrix to test
 |      :type x: numpy.ndarray
 |      :return: true if the matrix is a valid element of SE(2), ie. it is a
 |               3x3 homogeneous rigid-body transformation matrix.
 |      :rtype: bool
 |
 |      :seealso: :func:`~spatialmath.base.transform2d.ishom`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (3,3)
 |      :rtype: tuple
 |
 |  t
 |      Translational component of SE(2)
 |
 |      :param self: SE(2)
 |      :type self: SE2 instance
 |      :return: translational component
 |      :rtype: numpy.ndarray
 |
 |      ``x.t`` is the translational vector component.  If ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(2,)
 |      - N>1, return an ndarray with shape=(N,2)
 |
 |  x
 |      First element of the translational component of SE(2)
 |
 |      :param self: SE(2)
 |      :type self: SE2 instance
 |      :return: translational component
 |      :rtype: float
 |
 |      ``v.x`` is the first element of the translational vector component.  If ``len(x)`` is:
 |
 |      - 1, return an float
 |      - N>1, return an ndarray with shape=(N,)
 |
 |  y
 |      Second element of the translational component of SE(2)
 |
 |      :param self: SE(2)
 |      :type self: SE2 instance
 |      :return: translational component
 |      :rtype: float
 |
 |      ``v.y`` is the second element of the translational vector component.  If ``len(x)`` is:
 |
 |      - 1, return an float
 |      - N>1, return an ndarray with shape=(N,)
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SO2:
 |
 |  SE2(self)
 |      Create SE(2) from SO(2)
 |
 |      :return: SE(2) with same rotation but zero translation
 |      :rtype: SE2 instance
 |
 |  theta(self, unit='rad')
 |      SO(2) as a rotation angle
 |
 |      :param unit: angular units 'deg' or 'rad' [default]
 |      :type unit: str, optional
 |      :return: rotation angle
 |      :rtype: float or list
 |
 |      ``x.theta`` is the rotation angle such that `x` is `SO2(x.theta)`.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SO2:
 |
 |  R
 |      SO(2) or SE(2) as rotation matrix
 |
 |      :return: rotational component
 |      :rtype: numpy.ndarray, shape=(2,2)
 |
 |      ``x.R`` returns the rotation matrix, when `x` is `SO2` or `SE2`. If `len(x)` is:
 |
 |      - 1, return an ndarray with shape=(2,2)
 |      - N>1, return ndarray with shape=(N,2,2)
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __add__(left, right)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Add the elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
 |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
 |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ========================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ========================
 |      Pose             Pose             NxN matrix   element-wise matrix sum
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ========================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar + Pose is handled by :meth:`__radd__`
 |          #. Addition is commutative
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose addition either or both operands may hold more than one value which
 |      results in the sum holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``sum = left + right``
 |       1          M             M    ``sum[i] = left + right[i]``
 |       N          1             M    ``sum[i] = left[i] + right``
 |       M          M             M    ``sum[i] = left[i] + right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __eq__(left, right: 'Self') -> 'bool'
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for equality
 |
 |      ``X == Y`` is true of the poses are of the same type and numerically
 |      equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the equality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``eq = left == right``
 |       1          M             M    ``eq[i] = left == right[i]``
 |       N          1             M    ``eq[i] = left[i] == right``
 |       M          M             M    ``eq[i] = left[i] == right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __iadd__(left, right)
 |      Overloaded ``+=`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
 |      - ``X += s`` elementwise addition of the matrix elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__add__``
 |
 |  __imul__(left, right)
 |      Overloaded ``*=`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
 |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__mul__``
 |
 |  __isub__(left, right: 'Self')
 |      Overloaded ``-=`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises: ValueError
 |
 |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
 |        and ``Y`` and places the result in ``X``
 |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
 |        and the scalar ``s`` and places the result in ``X``
 |
 |      :seealso: ``__sub__``
 |
 |  __itruediv__(left, right)
 |      Overloaded ``/=`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
 |      - ``X /= s`` performs elementwise division of the elements of ``X``
 |        by ``s`` and places the result in ``X``
 |
 |      :seealso: ``__truediv__``
 |
 |  __matmul__(left, right)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :return: Product of two operands with normalization
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
 |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
 |        and places the result in ``X``
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally
 |          update over many cycles.
 |
 |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Pose composition, scaling or vector transformation:
 |
 |      - ``X * Y`` compounds the poses ``X`` and ``Y``
 |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
 |
 |      ==============   ==============   ===========  ======================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ======================
 |      Pose             Pose             Pose         matrix product
 |      Pose             scalar           NxN matrix   element-wise product
 |      scalar           Pose             NxN matrix   element-wise product
 |      Pose             N-vector         N-vector     vector transform
 |      Pose             NxM matrix       NxM matrix   transform each column
 |      ==============   ==============   ===========  ======================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar x Pose is handled by __rmul__`
 |          #. Scalar multiplication is commutative but the result is not a group
 |             operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
 |          SE3(array([[0., 0., 1., 0.],
 |                  [1., 0., 0., 0.],
 |                  [0., 1., 0., 0.],
 |                  [0., 0., 0., 1.]]))
 |          >>> SE3.Rx(pi/2) * 2
 |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
 |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
 |
 |      For vector transformation there are three cases:
 |
 |      =========  ===========  =====  ==========================
 |            Multiplicands             Product
 |      ----------------------  ---------------------------------
 |      len(left)  right.shape  shape  operation
 |      =========  ===========  =====  ==========================
 |      1          (N,)         (N,)   vector transformation
 |      M          (N,)         (N,M)  vector transformations
 |      1          (N,M)        (N,M)  column transformation
 |      =========  ===========  =====  ==========================
 |
 |      .. note::
 |          - The vector is an array-like, a 1D NumPy array or a list/tuple
 |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
 |            form, transformed, then converted back to Euclidean form.
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * [0, 1, 0]
 |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
 |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
 |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :return: Inequality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for inequality
 |
 |      - ``X != Y`` is true of the poses are of the same type but not numerically
 |        equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the inequality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``ne = left != right``
 |       1          M             M    ``ne[i] = left != right[i]``
 |       N          1             M    ``ne[i] = left[i] != right``
 |       M          M             M    ``ne[i] = left[i] != right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __pow__(self, n: 'int') -> 'Self'
 |      Overloaded ``**`` operator (superclass method)
 |
 |      :param n: exponent
 |      :type n: int
 |      :return: pose to the power ``n``
 |      :rtype: pose instance
 |
 |      ``X**n`` raise all values held in `X` to the specified power using repeated
 |      multiplication.  If ``n`` < 0 then the result is inverted.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.1) ** 2
 |          >>> SE3.Rx([0, 0.1]) ** 2
 |
 |  __radd__(right, left)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__add__`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> repr(x)
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Left-multiplication
 |
 |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
 |        elements of ``X`` by ``s`` and the result is a NumPy array.
 |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
 |        of ``A`` and ``X`` and the result is a NumPy array.
 |
 |      :seealso: :func:`__mul__`
 |
 |  __rsub__(right, left: 'Self')
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__sub__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of pose (superclass method)
 |
 |      :return: readable representation of the pose
 |      :rtype: str
 |
 |      Convert the pose's matrix value to a simple grid of numbers.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x)
 |
 |      Notes:
 |
 |          - By default, the output is colorised for an ANSI terminal console:
 |
 |              * red: rotational elements
 |              * blue: translational elements
 |              * white: constant elements
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Subtract elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
 |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
 |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ==============================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ==============================
 |      Pose             Pose             NxN matrix   element-wise matrix difference
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ==============================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar - Pose is handled by :meth:`__rsub__`
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose subtraction either or both operands may hold more than one value which
 |      results in the difference holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``diff = left - right``
 |       1          M             M    ``diff[i] = left - right[i]``
 |       N          1             M    ``diff[i] = left[i] - right``
 |       M          M             M    ``diff[i] = left[i]  right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __truediv__(left, right)
 |      Overloaded ``/`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      Pose composition or scaling:
 |
 |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
 |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
 |
 |      ==============   ==============   ===========  =========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   --------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  =========================
 |      Pose             Pose             Pose         matrix product by inverse
 |      Pose             scalar           NxN matrix   element-wise division
 |      ==============   ==============   ===========  =========================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar multiplication is not a group operation so the result will
 |             be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |  animate(self, *args, start=None, **kwargs) -> 'None'
 |      Plot pose object as an animated coordinate frame (superclass method)
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: same as ``self``
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
 |        from the origin in either 2D or 3D.  There are many options, see the
 |        links below.
 |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
 |        frame moving from pose ``X1``, in either 2D or 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=SE3.Ry(0.2))
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
 |
 |  conjugation(self, A: 'NDArray') -> 'NDArray'
 |      Matrix conjugation
 |
 |      :param A: matrix to conjugate
 |      :type A: ndarray
 |      :return: conjugated matrix
 |      :rtype: ndarray
 |
 |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
 |      is the current object.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO2
 |          >>> import numpy as np
 |          >>> R = SO2(0.5)
 |          >>> A = np.array([[10, 0], [0, 1]])
 |          >>> print(R * A * R.inv())
 |          >>> print(R.conjugation(A))
 |
 |  det(self) -> 'Tuple[float, Rn]'
 |      Determinant of rotational component (superclass method)
 |
 |      :return: Determinant of rotational component
 |      :rtype: float or NumPy array
 |
 |      ``x.det()`` is the determinant of the rotation component of the values
 |      of ``x``.
 |
 |      Example::
 |
 |          >>> x=SE3.Rand()
 |          >>> x.det()
 |          1.0000000000000004
 |          >>> x=SE3.Rand(N=2)
 |          >>> x.det()
 |          [0.9999999999999997, 1.0000000000000002]
 |
 |      :SymPy: not supported
 |
 |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
 |      Interpolate between poses (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :param shortest: take the shortest path along the great circle for the rotation
 |      :type shortest: bool, default to True
 |      :return: interpolated pose
 |      :rtype: same as ``self``
 |
 |      - ``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.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
 |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
 |          >>> x.interp(y, 0)    # this is x
 |          >>> x.interp(y, 1)    # this is y
 |          >>> x.interp(y, 0.5)  # this is in between
 |          >>> z = x.interp(y, 11)  # in 11 steps
 |          >>> len(z)
 |          >>> z[0]              # this is x
 |          >>> z[5]              # this is in between
 |
 |      .. note::
 |
 |          - 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
 |
 |  interp1(self, s: 'float' = None) -> 'Self'
 |      Interpolate pose (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1
 |      :type s: array_like
 |      :return: interpolated pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
 |
 |          ======  ======  ===========  ===============================
 |          len(X)  len(s)  len(result)  Result
 |          ======  ======  ===========  ===============================
 |          1       1       1            Y = interp(X, s)
 |          M       1       M            Y[i] = interp(X[i], s)
 |          1       M       M            Y[i] = interp(X, s[i])
 |          ======  ======  ===========  ===============================
 |
 |      Example::
 |
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x.interp(0))
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |          >>> print(x.interp(1))
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
 |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |          >>> y = x.interp(x, np.linspace(0, 1, 10))
 |          >>> len(y)
 |          10
 |          >>> y[5]
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
 |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |
 |      Notes:
 |
 |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
 |
 |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
 |
 |      :SymPy: not supported
 |
 |  ishom(self) -> 'bool'
 |      Test if object belongs to SE(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          True
 |
 |  ishom2(self) -> 'bool'
 |      Test if object belongs to SE(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          True
 |
 |  isrot(self) -> 'bool'
 |      Test if object belongs to SO(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          False
 |
 |  isrot2(self) -> 'bool'
 |      Test if object belongs to SO(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          False
 |
 |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
 |      Logarithm of pose (superclass method)
 |
 |      :return: logarithm
 |      :rtype: ndarray
 |      :raises: ValueError
 |
 |      An efficient closed-form solution of the matrix logarithm.
 |
 |      =====  ======  ===============================
 |      Input         Output
 |      -----  ---------------------------------------
 |      Pose   Shape   Structure
 |      =====  ======  ===============================
 |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
 |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
 |      =====  ======  ===============================
 |
 |      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. ]])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
 |      :func:`~spatialmath.base.transforms3d.trlog`
 |
 |      :SymPy: not supported
 |
 |  norm(self) -> 'Self'
 |      Normalize pose (superclass method)
 |
 |      :return: pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
 |        part of all values has been adjusted to ensure it is a proper orthogonal
 |        matrix rotation.
 |
 |      Example::
 |
 |          >>> x = SE3()
 |          >>> y = x.norm()
 |          >>> y
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |
 |      Notes:
 |
 |      #. Only the direction of A vector (the z-axis) is unchanged.
 |      #. Used to prevent finite word length arithmetic causing transforms to
 |         become 'unnormalized'.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
 |
 |  plot(self, *args, **kwargs) -> 'None'
 |      Plot pose object as a coordinate frame (superclass method)
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
 |        2D or 3D.  There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.plot(frame='A', color='green')
 |
 |      .. plot::
 |
 |          from spatialmath import SE3
 |          X = SE3.Rx(0.3)
 |          X.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
 |
 |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
 |      Print pose as a matrix (superclass method)
 |
 |      :param label: label to print before the matrix, defaults to None
 |      :type label: str, optional
 |      :param file: file to write to, defaults to None
 |      :type file: file object, optional
 |
 |      Print the pose as a matrix, with an optional line beforehand.  By default
 |      the matrix is printed to stdout.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3().print()
 |          >>> SE3().print("pose is:")
 |
 |      :seealso: :meth:`printline` :meth:`strline`
 |
 |  printline(self, *args, **kwargs) -> 'None'
 |      Print pose in compact single line format (superclass method)
 |
 |      :param arg: value for orient option, optional
 |      :type arg: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param file: file to write formatted string to. [default, stdout]
 |      :type file: file object
 |
 |      Print pose in a compact single line format. If ``X`` has multiple
 |      values, print one per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.printline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.printline()
 |          >>> x.printline('angvec')
 |          >>> x.printline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.printline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
 |
 |  prod(self, norm=False, check=True) -> 'Self'
 |      Product of elements (superclass method)
 |
 |      :param norm: normalize the product, defaults to False
 |      :type norm: bool, optional
 |      :param check: check that computed matrix is valid member of group, default True
 |      :bool check: bool, optional
 |      :return: Product of elements
 |      :rtype: pose instance
 |
 |      ``x.prod()`` is the product of the values held by ``x``, ie.
 |      :math:`\prod_i^N T_i`.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
 |          >>> x.prod()
 |
 |      .. note:: When compounding many transformations the product may become
 |          denormalized resulting in a result that is not a proper member of the
 |          group.  You can either disable membership checking by ``check=False``
 |          which is risky, or normalize the result by ``norm=True``.
 |
 |  simplify(self) -> 'Self'
 |      Symbolically simplify matrix values (superclass method)
 |
 |      :return: pose with symbolic elements
 |      :rtype: pose instance
 |
 |      Apply symbolic simplification to every element of every value in the
 |      pose instance.
 |
 |      Example::
 |
 |          >>> a = SE3.Rx(sympy.symbols('theta'))
 |          >>> b = a * a
 |          >>> b
 |          SE3(array([[1, 0, 0, 0.0],
 |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
 |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
 |          [0.0, 0, 0, 1.0]], dtype=object)
 |          >>> b.simplify()
 |          SE3(array([[1, 0, 0, 0],
 |          [0, cos(2*theta), -sin(2*theta), 0],
 |          [0, sin(2*theta), cos(2*theta), 0],
 |          [0, 0, 0, 1.00000000000000]], dtype=object))
 |
 |      .. todo:: No need to simplify the constants in bottom row
 |
 |      :SymPy: supported
 |
 |  stack(self) -> 'NDArray'
 |      Convert to 3-dimensional matrix
 |
 |      :return: 3-dimensional NumPy array
 |      :rtype: ndarray(n,n,m)
 |
 |      Converts the value to a 3-dimensional NumPy array where the values are
 |      stacked along the third axis.  The first two dimensions are given by
 |      ``self.shape``.
 |
 |  strline(self, *args, **kwargs) -> 'str'
 |      Convert pose to compact single line string (superclass method)
 |
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: pose in string format
 |      :rtype: str
 |
 |      Convert pose in a compact single line format. If ``X`` has multiple
 |      values, the string has one pose per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.strline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.strline()
 |          >>> x.strline('angvec')
 |          >>> x.strline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.strline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
 |
 |  ----------------------------------------------------------------------
 |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __new__(cls, *args, **kwargs)
 |      Create the subclass instance (superclass method)
 |
 |      Create a new instance and call the superclass initializer to enable the
 |      ``UserList`` capabilities.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  N
 |      Dimension of the object's group (superclass property)
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
 |      This corresponds to the dimension of the space, 2D or 3D, to which these
 |      rotations or rigid-body motions apply.
 |
 |      Example::
 |
 |          >>> SE3().N
 |          3
 |          >>> SE2().N
 |          2
 |
 |  about
 |      Succinct summary of object type and length (superclass property)
 |
 |      :return: succinct summary
 |      :rtype: str
 |
 |      Displays the type and the number of elements in compact form, for
 |      example::
 |
 |          >>> x = SE3([SE3() for i in range(20)])
 |          >>> len(x)
 |          20
 |          >>> print(x.about)
 |          SE3[20]
 |
 |  isSE
 |      Test if object belongs to SE(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SE2 or SE3
 |      :rtype: bool
 |
 |  isSO
 |      Test if object belongs to SO(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SO2 or SO3
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __len__(self)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SE3
Python Library Documentation: class SE3 in module spatialmath.pose3d

class SE3(SO3)
 |  SE3(x=None, y=None, z=None, *, check=True)
 |
 |     SE(3) matrix class
 |
 |     This subclass represents rigid-body motion in 3D space.  Internally it is a
 |     4x4 homogeneous transformation matrix belonging to the group SE(3).
 |
 |  .. inheritance-diagram:: spatialmath.pose3d.SE3
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  Method resolution order:
 |      SE3
 |      SO3
 |      spatialmath.baseposematrix.BasePoseMatrix
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  Ad(self) -> 'R6x6'
 |      Adjoint of SE(3)
 |
 |      :return: adjoint matrix
 |      :rtype: ndarray(6,6)
 |
 |      ``SE3.Ad`` is the 6x6 adjoint matrix
 |
 |      If spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
 |      and the SE(3) represents the pose of {B} relative to {A},
 |      ie. :math:`{}^A {\bf T}_B`, and the adjoint is :math:`\mathbf{A}` then
 |      :math:`{}^{A}\!\nu = \mathbf{A} {}^{B}\!\nu`.
 |
 |      .. warning:: Do not use this method to map velocities
 |          between robot base and end-effector frames - use ``jacob()``.
 |
 |      .. note:: Use this method to map velocities between two frames on
 |          the same rigid-body.
 |
 |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
 |      :seealso: SE3.jacob, Twist.ad, :func:`~spatialmath.base.tr2jac`
 |      :SymPy: supported
 |
 |  __init__(self, x=None, y=None, z=None, *, check=True)
 |      Construct new SE(3) object
 |
 |      :rtype: SE3 instance
 |
 |      There are multiple call signatures that return an ``SE3`` instance
 |      with one or more values.
 |
 |      - ``SE3()`` null motion, value is the identity matrix.
 |      - ``SE3(x, y, z)`` is a pure translation of (x,y,z)
 |      - ``SE3(T)``  where ``T`` is a 4x4 Numpy  array representing an SE(3)
 |        matrix.  If ``check`` is ``True`` check the matrix belongs to SE(3).
 |      - ``SE3([T1, T2, ... TN])`` has ``N`` values
 |        given by the elements ``Ti`` each of which is a 4x4 NumPy array
 |        representing an SE(3) matrix. If ``check`` is ``True`` check the
 |        matrix belongs to SE(3).
 |      - ``SE3(X)`` where ``X`` is:
 |        -  ``SE3`` is a copy of ``X``
 |        -  ``SO3`` is the rotation of ``X`` with zero translation
 |        -  ``SE2`` is the z-axis rotation and x- and y-axis translation of
 |           ``X``
 |      - ``SE3([X1, X2, ... XN])`` has ``N`` values
 |        given by the elements ``Xi`` each of which is an SE3 instance.
 |
 |      :SymPy: supported
 |
 |  angdist(self, other: 'SE3', metric: 'int' = 6) -> 'float'
 |      Angular distance metric between poses
 |
 |      :param other: second rotation
 |      :type other: SE3 instance
 |      :param metric: metric, default is 6
 |      :type metric: int
 |      :raises TypeError: if other is not an SE3
 |      :return: angle in radians
 |      :rtype: float or ndarray
 |
 |      ``T1.angdist(T2)`` is the geodesic norm, or geodesic distance between the
 |      rotational parts of the two poses.
 |
 |      Several metrics are supported, the first 5 are computed after conversion
 |      to unit quaternions.
 |
 |      ======   ===============================================================
 |      Metric   Details
 |      ======   ===============================================================
 |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
 |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      3        :math:`2 \tan^{-1} \| \q_1 - \q_2\| / \|\q_1 + \q_2\| \in [0, \pi/2]`
 |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
 |      5        :math:`\|I - \mat{R}_1 \mat{R}_2^T\| \in [0, 2]`
 |      6        :math:`\|\log \mat{R}_1 \mat{R}_2^T\| \in [0, \pi]`
 |      ======   ===============================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> T1 = SE3.Rx(0.3)
 |          >>> T2 = SE3.Ry(0.3)
 |          >>> print(T1.angdist(T1))
 |          >>> print(T1.angdist(T2))
 |
 |      .. note::
 |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
 |            numeric errors which push the argument of ``acos()`` marginally
 |            outside its domain [0, 1].
 |          - metrics 2 and 3 are equivalent, but 3 is more robust
 |
 |      :seealso: :func:`UnitQuaternion.angdist`
 |
 |  delta(self, X2: 'Optional[SE3]' = None) -> 'R6'
 |      Infinitesimal difference of SE(3) values
 |
 |      :return: differential motion vector
 |      :rtype: ndarray(6)
 |
 |      ``X1.delta(X2)`` is the differential motion (6x1) corresponding to
 |      infinitesimal motion (in the ``X1`` frame) from pose ``X1`` to ``X2``.
 |
 |      The vector :math:`d = [\delta_x, \delta_y, \delta_z, \theta_x, \theta_y, \theta_z]`
 |      represents infinitesimal translation and rotation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x1 = SE3.Rx(0.3)
 |          >>> x2 = SE3.Rx(0.3001)
 |          >>> x1.delta(x2)
 |
 |      .. note::
 |
 |          - the displacement is only an approximation to the motion, and assumes
 |            that ``X1`` ~ ``X2``.
 |          - can be considered as an approximation to the effect of spatial velocity over a
 |            a time interval, ie. the average spatial velocity multiplied by time.
 |
 |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tr2delta`
 |
 |  inv(self) -> 'SE3'
 |      Inverse of SE(3)
 |
 |      :return: inverse
 |      :rtype: SE3 instance
 |
 |      Efficiently compute the inverse of each of the SE(3) values taking into
 |      account the matrix structure.
 |
 |      .. math::
 |
 |          T = \left[ \begin{array}{cc} \mat{R} & \vec{t} \\ 0 & 1 \end{array} \right],
 |          \mat{T}^{-1} = \left[ \begin{array}{cc} \mat{R}^T & -\mat{R}^T \vec{t} \\ 0 & 1 \end{array} \right]`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3(1,2,3)
 |          >>> x.inv()
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trinv`
 |
 |      :SymPy: supported
 |
 |  jacob(self) -> 'R6x6'
 |      Velocity transform for SE(3)
 |
 |      :return: Jacobian matrix
 |      :rtype: ndarray(6,6)
 |
 |      ``SE3.jacob()`` is the 6x6 Jacobian that maps spatial velocity or
 |      differential motion from frame {B} to frame {A} where the pose of {B}
 |      relative to {A} is represented by the homogeneous transform T =
 |      :math:`{}^A {\bf T}_B`.
 |
 |      .. note::
 |          - To map from frame {A} to frame {B} use the transpose of this matrix.
 |          - Use this method to map velocities between the robot end-effector frame
 |            and the base frames.
 |
 |      .. warning:: Do not use this method to map velocities between two frames
 |          on the same rigid-body.
 |
 |      :seealso: SE3.Ad, Twist.ad, :func:`~spatialmath.base.tr2jac`
 |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
 |      :SymPy: supported
 |
 |  mean(self, tol: 'float' = 20) -> 'SE3'
 |      Mean of a set of SE(3) values
 |
 |      :param tol: iteration tolerance in units of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: the mean SE(3) pose
 |      :rtype: :class:`SE3` instance.
 |
 |      Computes the mean of all the SE(3) values within the :class:`SE3` instance.  Rotations are
 |      averaged using the Karcher mean, and translations are averaged using the
 |      arithmetic mean.
 |
 |      :references:
 |          - `**Hartley, Trumpf** - "Rotation Averaging" - IJCV 2011 <https://users.cecs.anu.edu.au/~hartley/Papers/PDF/Hartley-Trumpf:Rotation-averaging:IJCV.pdf>`_, Algorithm 1, page 15.
 |          - `Karcher mean <https://en.wikipedia.org/wiki/Karcher_mean>`_
 |
 |      :seealso:  :meth:`SO3.mean`
 |
 |  rtvec(self) -> 'Tuple[R3, R3]'
 |      Convert to OpenCV-style rotation and translation vectors
 |
 |      :return: rotation and translation vectors
 |      :rtype: ndarray(3), ndarray(3)
 |
 |      Many OpenCV functions accept pose as two 3-vectors: a rotation vector using
 |      exponential coordinates and a translation vector.  This method combines them
 |      into an SE(3) instance.
 |
 |      :seealso: :meth:`rtvec`
 |
 |  twist(self) -> 'Twist3'
 |      SE(3) as twist
 |
 |      :return: equivalent rigid-body motion as a twist vector
 |      :rtype: Twist3 instance
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3(1,2,3)
 |          >>> x.twist()
 |
 |      :seealso: :func:`spatialmath.twist.Twist3`
 |
 |  yaw_SE2(self, order: 'str' = 'zyx') -> 'SE2'
 |      Create SE(2) from SE(3) yaw angle.
 |
 |      :param order: angle sequence order, default to 'zyx'
 |      :type order: str
 |      :return: SE(2) with same rotation as the yaw angle using the roll-pitch-yaw convention,
 |          and translation along the roll-pitch axes.
 |      :rtype: SE2 instance
 |
 |      Roll-pitch-yaw corresponds to successive rotations about the axes specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
 |            to the optic axis and x-axis parallel to the pixel rows.
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  AngVec(theta: 'float', v: 'ArrayLike3', *, unit: 'str' = 'rad') -> 'SE3'
 |      Create an SE(3) pure rotation matrix from rotation angle and axis
 |
 |      :param θ: rotation
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param v: rotation axis
 |      :type v: array_like(3)
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      ``SE3.AngVec(θ, v)`` is an SE(3) rotation defined by
 |      a rotation of ``θ`` about the vector ``v``.
 |
 |      .. deprecated:: 0.9.8
 |          Use :meth:`AngleAxis` instead.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.pose3d.SE3.EulerVec`, :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  AngleAxis(theta: 'float', v: 'ArrayLike3', *, unit: 'Optional[unit]' = 'rad') -> 'SE3'
 |      Create an SE(3) pure rotation matrix from rotation angle and axis
 |
 |      :param θ: rotation
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param v: rotation axis
 |      :type v: array_like(3)
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      ``SE3.AngleAxis(θ, v)`` is an SE(3) rotation defined by
 |      a rotation of ``θ`` about the vector ``v``.
 |
 |      .. math::
 |
 |          \mbox{if}\,\, \theta \left\{ \begin{array}{ll}
 |              = 0 & \mbox{return identity matrix}\\
 |              \ne 0 & \mbox{v must have a finite length}
 |              \end{array}
 |              \right.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.pose3d.SE3.EulerVec`, :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  CopyFrom(T: 'SE3Array', check: 'bool' = True) -> 'SE3'
 |      Create an SE(3) from a 4x4 numpy array that is passed by value.
 |
 |      :param T: homogeneous transformation
 |      :type T: ndarray(4, 4)
 |      :param check: check rotation validity, defaults to True
 |      :type check: bool, optional
 |      :raises ValueError: bad rotation matrix, bad transformation matrix
 |      :return: SE(3) matrix representing that transformation
 |      :rtype: SE3 instance
 |
 |  Delta(d: 'ArrayLike6') -> 'SE3'
 |      Create SE(3) from differential motion
 |
 |      :param d: differential motion
 |      :type d: array_like(6)
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      ``SE3.Delta2tr(d)`` is an SE(3) representing differential
 |      motion :math:`d = [\delta_x, \delta_y, \delta_z, \theta_x, \theta_y, \theta_z]`.
 |
 |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
 |
 |      :seealso: :meth:`~delta` :func:`~spatialmath.base.transform3d.delta2tr`
 |      :SymPy: supported
 |
 |  Eul(*angles, unit='rad') -> 'SE3'
 |      Create an SE(3) pure rotation from Euler angles
 |
 |      :param 𝚪: Euler angles
 |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Eul(𝚪)`` is an SE(3) rotation defined by a 3-vector of Euler
 |        angles :math:`\Gamma=(\phi, \theta, \psi)` which correspond to
 |        consecutive rotations about the Z, Y, Z axes respectively.
 |
 |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of
 |      rotations each defined by Euler angles corresponding to the rows of
 |      ``𝚪``.
 |
 |      - ``SE3.Eul(φ, θ, ψ)`` as above but the angles are provided as three
 |        scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Eul(0.1, 0.2, 0.3)
 |          >>> SE3.Eul([0.1, 0.2, 0.3])
 |          >>> SE3.Eul(10, 20, 30, unit="deg")
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.eul`, :func:`~spatialmath.base.transforms3d.eul2r`
 |      :SymPy: supported
 |
 |  EulerVec(w: 'ArrayLike3') -> 'SE3'
 |      Construct a new SE(3) pure rotation matrix from an Euler rotation vector
 |
 |      :param ω: rotation axis
 |      :type ω: array_like(3)
 |      :return: SE(3) rotation
 |      :rtype: SE3 instance
 |
 |      ``SE3.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
 |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
 |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.EulerVec([0.5,0,0])
 |
 |      .. note:: :math:`\theta = 0` the result in an identity matrix, otherwise
 |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.AngVec`, :func:`~spatialmath.base.transforms3d.angvec2tr`
 |
 |  Exp(S: 'Union[R6, R4x4]', check: 'bool' = True) -> 'SE3'
 |      Create an SE(3) matrix from se(3)
 |
 |      :param S: Lie algebra se(3) matrix
 |      :type S: ndarray(6), ndarray(4,4)
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Exp(S)`` is an SE(3) rotation defined by its Lie algebra
 |        which is a 4x4 se(3) matrix (skew symmetric)
 |      - ``SE3.Exp(t)`` is an SE(3) rotation defined by a 6-element twist
 |        vector (the unique elements of the se(3) skew-symmetric matrix)
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trexp`, :func:`~spatialmath.base.transformsNd.skew`
 |
 |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'SE3'
 |      Create an SE(3) pure rotation from two vectors
 |
 |      :param o: 3-vector parallel to Y- axis
 |      :type o: array_like(3)
 |      :param a: 3-vector parallel to the Z-axis
 |      :type a: array_like(3)
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      ``SE3.OA(o, a)`` is an SE(3) rotation defined in terms of vectors ``o``
 |      and ``a`` respectively parallel to the Y- and Z-axes of its reference
 |      frame.  In robotics these axes are respectively called the *orientation*
 |      and *approach* vectors defined such that :math:`\mathbf{R} = [n, o, a]`
 |      and :math:`n = o \times a`.
 |
 |      .. note::
 |
 |          - The ``a`` vector is the only guaranteed to have the same direction in the resulting
 |            rotation matrix
 |          - ``o`` and ``a`` do not have to be unit-length, they are normalized
 |          - ``o`` and ``a`` do not have to be orthogonal, so long as they are not parallel
 |            ``o`` is adjusted to be orthogonal to ``a``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.OA([1, 0, 0], [0, 0, -1])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.oa2r`
 |
 |  RPY(*angles, unit='rad', order='zyx') -> 'SE3'
 |      Create an SE(3) pure rotation from roll-pitch-yaw angles
 |
 |      :param 𝚪: roll-pitch-yaw angles
 |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
 |      :type order: str
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.RPY(𝚪)`` is an SE(3) rotation defined by a 3-vector of roll,
 |        pitch, yaw angles :math:`\Gamma=(r, p, y)` which correspond to
 |        successive rotations about the axes specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  This is the **convention** for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. This is the **convention** for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. This is the **convention** for a camera with z-axis parallel
 |            to the optical axis and x-axis parallel to the pixel rows.
 |
 |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of rotations each defined by RPY angles
 |      corresponding to the rows of ``𝚪``.
 |
 |      - ``SE3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
 |        scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.RPY(0.1, 0.2, 0.3)
 |          >>> SE3.RPY([0.1, 0.2, 0.3])
 |          >>> SE3.RPY(0.1, 0.2, 0.3, order='xyz')
 |          >>> SE3.RPY(10, 20, 30, unit='deg')
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.rpy`, :func:`~spatialmath.base.transforms3d.rpy2r`
 |      :SymPy: supported
 |
 |  RTvec(rvec: 'ArrayLike3', tvec: 'ArrayLike3') -> 'Self'
 |      Construct a new SE(3) from OpenCV-style rotation and translation vectors
 |
 |      :param rvec: rotation as exponential coordinates
 |      :type rvec: ArrayLike3
 |      :param tvec: translation vector
 |      :type tvec: ArrayLike3
 |      :return: An SE(3) instance
 |      :rtype: SE3 instance
 |
 |      Many OpenCV functions (such as pose estimation) return pose as two 3-vectors: a
 |      rotation vector using exponential coordinates and a translation vector.  This
 |      method combines them into an SE(3) instance.
 |
 |      :seealso: :meth:`rtvec`
 |
 |  Rand(N: 'int' = 1, xrange: 'Optional[ArrayLike2]' = (-1, 1), yrange: 'Optional[ArrayLike2]' = (-1, 1), zrange: 'Optional[ArrayLike2]' = (-1, 1), theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'SE3'
 |      Create a random SE(3)
 |
 |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
 |      :type xrange: 2-element sequence, optional
 |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
 |      :type yrange: 2-element sequence, optional
 |      :param zrange: z-axis range [min,max], defaults to [-1, 1]
 |      :type zrange: 2-element sequence, optional
 |      :param theta_range: angular magnitude range [min,max], defaults to None -> [0,pi].
 |      :type xrange: 2-element sequence, optional
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param N: number of random transforms
 |      :type N: int
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      Return an SE3 instance with random rotation and translation.
 |
 |      - ``SE3.Rand()`` is a random SE(3) translation.
 |      - ``SE3.Rand(N)`` is an SE3 object containing a sequence of N random
 |        poses.
 |
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rand(2)
 |
 |      :seealso: :func:`~spatialmath.quaternions.UnitQuaternion.Rand`
 |
 |  Rt(R: 'Union[SO3, SO3Array]', t: 'Optional[ArrayLike3]' = None, check: 'bool' = True) -> 'SE3'
 |      Create an SE(3) from rotation and translation
 |
 |      :param R: rotation
 |      :type R: SO3 or ndarray(3,3)
 |      :param t: translation
 |      :type t: array_like(3)
 |      :param check: check rotation validity, defaults to True
 |      :type check: bool, optional
 |      :raises ValueError: bad rotation matrix
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |  Rx(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
 |      Create anSE(3) pure rotation about the X-axis
 |
 |      :param θ: rotation angle about X-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param t: translation, optional
 |      :type t: 3-element array-like
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Rx(θ)`` is an SE(3) rotation of θ radians about the x-axis
 |      - ``SE3.Rx(θ, "deg")`` as above but θ is in degrees
 |      - ``SE3.Rx(θ, t=T)`` as above but also sets the translational component
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      .. note:: The translation option only works for the scalar θ case.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.3)
 |          >>> SE3.Rx([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trotx`
 |      :SymPy: supported
 |
 |  Ry(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
 |      Create an SE(3) pure rotation about the Y-axis
 |
 |      :param θ: rotation angle about X-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param t: translation, optional
 |      :type t: 3-element array-like
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Ry(θ)`` is an SO(3) rotation of θ radians about the y-axis
 |      - ``SE3.Ry(θ, "deg")`` as above but θ is in degrees
 |      - ``SE3.Ry(θ, t=T)`` as above but also sets the translational component
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      .. note:: The translation option only works for the scalar θ case.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Ry(0.3)
 |          >>> SE3.Ry([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.troty`
 |      :SymPy: supported
 |
 |  Rz(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
 |      Create an SE(3) pure rotation about the Z-axis
 |
 |      :param θ: rotation angle about Z-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param t: translation, optional
 |      :type t: 3-element array-like
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Rz(θ)`` is an SO(3) rotation of θ radians about the z-axis
 |      - ``SE3.Rz(θ, "deg")`` as above but θ is in degrees
 |      - ``SE3.Rz(θ, t=T)`` as above but also sets the translational component
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      .. note:: The translation option only works for the scalar θ case.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rz(0.3)
 |          >>> SE3.Rz([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trotz`
 |      :SymPy: supported
 |
 |  Trans(x, y=None, z=None) -> 'SE3'
 |      Create SE(3) from translation vector
 |
 |      :param x: x-coordinate or translation vector
 |      :type x: float or array_like(3)
 |      :param y: y-coordinate, defaults to None
 |      :type y: float, optional
 |      :param z: z-coordinate, defaults to None
 |      :type z: float, optional
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``SE3.Trans(x, y, z)`` is an SE(3) representing pure translation.
 |
 |      - ``SE3.Trans([x, y, z])`` as above, but translation is given as an
 |        array.
 |
 |      - ``SE3.Trans(t)`` where ``t`` is Nx3 then create an SE3 object with
 |        N elements whose translation is defined by the rows of ``t``.
 |
 |  Tx(x: 'float') -> 'SE3'
 |      Create an SE(3) translation along the X-axis
 |
 |      :param x: translation distance along the X-axis
 |      :type x: float
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      `SE3.Tx(x)` is an SE(3) translation of ``x`` along the x-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Tx(2)
 |          >>> SE3.Tx([2,3])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Ty(y: 'float') -> 'SE3'
 |      Create an SE(3) translation along the Y-axis
 |
 |      :param y: translation distance along the Y-axis
 |      :type y: float
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      `SE3.Ty(y) is an SE(3) translation of ``y`` along the y-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Ty(2)
 |          >>> SE3.Ty([2,3])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Tz(z: 'float') -> 'SE3'
 |      Create an SE(3) translation along the Z-axis
 |
 |      :param z: translation distance along the Z-axis
 |      :type z: float
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      `SE3.Tz(z)` is an SE(3) translation of ``z`` along the z-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Tz(2)
 |          >>> SE3.Tz([2,3])
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
 |      :SymPy: supported
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x: 'NDArray', check: 'bool' = True) -> 'bool'
 |      Test if matrix is a valid SE(3)
 |
 |      :param x: matrix to test
 |      :type x: numpy.ndarray
 |      :return: ``True`` if the matrix is 4x4 and a valid element of SE(3), ie. it
 |               is a valid homogeneous transformation matrix.
 |      :rtype: bool
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.ishom`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  shape
 |      Shape of the object's internal matrix representation
 |
 |      :return: (4,4)
 |      :rtype: tuple
 |
 |      Each value within the ``SE3`` instance is a NumPy array of this shape.
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  R
 |      SO(3) or SE(3) as rotation matrix
 |
 |      :return: rotational component
 |      :rtype: ndarray(3,3)
 |
 |      ``x.R`` is the rotation matrix component of ``x`` as an array with
 |      shape (3,3). If ``len(x) > 1``, return an array with shape=(N,3,3).
 |
 |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
 |          ``x[i]``. This is different to the MATLAB version where the i'th
 |          rotation matrix is ``x(:,:,i)``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> x = SO3.Rx(0.3)
 |          >>> x.R
 |
 |      :SymPy: supported
 |
 |  t
 |      Translational component of SE(3)
 |
 |      :return: translational component of SE(3)
 |      :rtype: numpy.ndarray
 |
 |      ``x.t`` is the translational component of ``x`` as an array with
 |      shape (3,). If ``len(x) > 1``, return an array with shape=(N,3).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3(1,2,3)
 |          >>> x.t
 |          >>> x = SE3([ SE3(1,2,3), SE3(4,5,6)])
 |          >>> x.t
 |
 |      :SymPy: supported
 |
 |  x
 |      First element of translational component of SE(3)
 |
 |      :return: first element of translational component of SE(3)
 |      :rtype: float
 |
 |      If ``len(v) > 1``, return an array with shape=(N,).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> v = SE3(1,2,3)
 |          >>> v.x
 |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
 |          >>> v.x
 |
 |      :SymPy: supported
 |
 |  y
 |      Second element of translational component of SE(3)
 |
 |      :return: second element of translational component of SE(3)
 |      :rtype: float
 |
 |      If ``len(v) > 1``, return an array with shape=(N,).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> v = SE3(1,2,3)
 |          >>> v.y
 |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
 |          >>> v.y
 |
 |      :SymPy: supported
 |
 |  z
 |      Third element of translational component of SE(3)
 |
 |      :return: third element of translational component of SE(3)
 |      :rtype: float
 |
 |      If ``len(v) > 1``, return an array with shape=(N,).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> v = SE3(1,2,3)
 |          >>> v.z
 |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
 |          >>> v.z
 |
 |      :SymPy: supported
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SO3:
 |
 |  UnitQuaternion(self) -> 'UnitQuaternion'
 |      SO3 as a unit quaternion instance
 |
 |      :return: a unit quaternion representation
 |      :rtype: UnitQuaternion instance
 |
 |      ``R.UnitQuaternion()`` is an ``UnitQuaternion`` instance representing the same rotation
 |      as the SO3 rotation ``R``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> SO3.Rz(0.3).UnitQuaternion()
 |
 |  angvec(self, unit: 'str' = 'rad') -> 'Tuple[float, R3]'
 |      SO(3) or SE(3) as angle and rotation vector
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: :math:`(\theta, \hat{\bf v})`
 |      :rtype: float or ndarray(3)
 |
 |      ``x.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
 |      angle and a rotation axis.
 |
 |      By default the angle is in radians but can be changed setting `unit='deg'`.
 |
 |      .. note::
 |
 |          - If the input is SE(3) the translation component is ignored.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> R = SO3.Rx(0.3)
 |          >>> R.angvec()
 |
 |      :seealso: :meth:`eulervec` :meth:`AngVec` :meth:`~spatialmath.quaternion.UnitQuaternion.angvec` :meth:`~spatialmath.quaternion.AngVec`, :func:`~angvec2r`
 |
 |  eul(self, unit: 'str' = 'rad', flip: 'bool' = False) -> 'Union[R3, RNx3]'
 |      SO(3) or SE(3) as Euler angles
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of Euler angles
 |      :rtype: ndarray(3,), ndarray(n,3)
 |
 |      ``x.eul`` is the Euler angle representation of the rotation.  Euler angles are
 |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
 |      rotations about the Z, Y, Z axes respectively.
 |
 |      If ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(3,N)
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.tr2eul`
 |      :SymPy: not supported
 |
 |  eulervec(self) -> 'R3'
 |      SO(3) or SE(3) as Euler vector (exponential coordinates)
 |
 |      :return: :math:`\theta \hat{\bf v}`
 |      :rtype: ndarray(3)
 |
 |      ``x.eulervec()`` is the Euler vector (or exponential coordinates) which
 |      is related to angle-axis notation and is the product of the rotation
 |      angle and the rotation axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> R = SO3.Rx(0.3)
 |          >>> R.eulervec()
 |
 |      .. note::
 |
 |          - If the input is SE(3) the translation component is ignored.
 |
 |      :seealso: :meth:`angvec` :func:`~angvec2r`
 |
 |  rpy(self, unit: 'str' = 'rad', order: 'str' = 'zyx') -> 'Union[R3, RNx3]'
 |      SO(3) or SE(3) as roll-pitch-yaw angles
 |
 |      :param order: angle sequence order, default to 'zyx'
 |      :type order: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of roll-pitch-yaw angles
 |      :rtype: ndarray(3,), ndarray(n,3)
 |
 |      ``x.rpy`` is the roll-pitch-yaw angle representation of the rotation.  The angles are
 |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
 |      specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
 |            to the optic axis and x-axis parallel to the pixel rows.
 |
 |      If `len(x)` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(3,N)
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.RPY`, :func:`~spatialmath.base.transforms3d.tr2rpy`
 |      :SymPy: not supported
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from SO3:
 |
 |  RotatedVector(v1: 'ArrayLike3', v2: 'ArrayLike3', tol=20) -> 'Self'
 |      Construct a new SO(3) from a vector and its rotated image
 |
 |      :param v1: initial vector
 |      :type v1: array_like(3)
 |      :param v2: vector after rotation
 |      :type v2: array_like(3)
 |      :param tol: tolerance for singularity in units of eps, defaults to 20
 |      :type tol: float
 |      :return: SO(3) rotation
 |      :rtype: :class:`SO3` instance
 |
 |      ``SO3.RotatedVector(v1, v2)`` is an SO(3) rotation defined in terms of
 |      two vectors. The rotation takes vector ``v1`` to ``v2``.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> v1 = [1, 2, 3]
 |          >>> v2 = SO3.Eul(0.3, 0.4, 0.5) * v1
 |          >>> print(v2)
 |          >>> R = SO3.RotatedVector(v1, v2)
 |          >>> print(R)
 |          >>> print(R * v1)
 |
 |      .. note:: The vectors do not have to be unit-length.
 |
 |  TwoVectors(x: 'Optional[Union[str, ArrayLike3]]' = None, y: 'Optional[Union[str, ArrayLike3]]' = None, z: 'Optional[Union[str, ArrayLike3]]' = None) -> 'Self'
 |      Construct a new SO(3) from any two vectors
 |
 |      :param x: new x-axis, defaults to None
 |      :type x: str, array_like(3), optional
 |      :param y: new y-axis, defaults to None
 |      :type y: str, array_like(3), optional
 |      :param z: new z-axis, defaults to None
 |      :type z: str, array_like(3), optional
 |
 |      Create a rotation by defining the direction of two of the new
 |      axes in terms of the old axes.  Axes are denoted by strings ``"x"``,
 |      ``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
 |
 |      The directions can also be specified by 3-element vectors. If the vectors are not orthogonal,
 |      they will orthogonalized w.r.t. the first available dimension. I.e. if x is available, it will be
 |      normalized and the remaining vector will be orthogonalized w.r.t. x, else, y will be normalized
 |      and z will be orthogonalized w.r.t. y.
 |
 |      To create a rotation where the new frame has its x-axis in -z-direction
 |      of the previous frame, and its z-axis in the x-direction of the previous
 |      frame is::
 |
 |          >>> SO3.TwoVectors(x='-z', z='x')
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SO3:
 |
 |  a
 |      Approach vector of SO(3) or SE(3)
 |
 |      :return: approach vector
 |      :rtype: ndarray(3)
 |
 |      This is the third column of the rotation submatrix, sometimes called the
 |      *approach vector*.  It is parallel to the z-axis of the frame defined by
 |      this pose.
 |
 |  n
 |      Normal vector of SO(3) or SE(3)
 |
 |      :return: normal vector
 |      :rtype: ndarray(3)
 |
 |      This is the first column of the rotation submatrix, sometimes called the
 |      *normal vector*.  It is parallel to the x-axis of the frame defined by
 |      this pose.
 |
 |  o
 |      Orientation vector of SO(3) or SE(3)
 |
 |      :return: orientation vector
 |      :rtype: ndarray(3)
 |
 |      This is the second column of the rotation submatrix, sometimes called
 |      the *orientation vector*.  It is parallel to the y-axis of the frame
 |      defined by this pose.
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __add__(left, right)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Add the elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
 |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
 |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ========================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ========================
 |      Pose             Pose             NxN matrix   element-wise matrix sum
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ========================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar + Pose is handled by :meth:`__radd__`
 |          #. Addition is commutative
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose addition either or both operands may hold more than one value which
 |      results in the sum holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``sum = left + right``
 |       1          M             M    ``sum[i] = left + right[i]``
 |       N          1             M    ``sum[i] = left[i] + right``
 |       M          M             M    ``sum[i] = left[i] + right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __eq__(left, right: 'Self') -> 'bool'
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for equality
 |
 |      ``X == Y`` is true of the poses are of the same type and numerically
 |      equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the equality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``eq = left == right``
 |       1          M             M    ``eq[i] = left == right[i]``
 |       N          1             M    ``eq[i] = left[i] == right``
 |       M          M             M    ``eq[i] = left[i] == right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __iadd__(left, right)
 |      Overloaded ``+=`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
 |      - ``X += s`` elementwise addition of the matrix elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__add__``
 |
 |  __imul__(left, right)
 |      Overloaded ``*=`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
 |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__mul__``
 |
 |  __isub__(left, right: 'Self')
 |      Overloaded ``-=`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises: ValueError
 |
 |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
 |        and ``Y`` and places the result in ``X``
 |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
 |        and the scalar ``s`` and places the result in ``X``
 |
 |      :seealso: ``__sub__``
 |
 |  __itruediv__(left, right)
 |      Overloaded ``/=`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
 |      - ``X /= s`` performs elementwise division of the elements of ``X``
 |        by ``s`` and places the result in ``X``
 |
 |      :seealso: ``__truediv__``
 |
 |  __matmul__(left, right)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :return: Product of two operands with normalization
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
 |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
 |        and places the result in ``X``
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally
 |          update over many cycles.
 |
 |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Pose composition, scaling or vector transformation:
 |
 |      - ``X * Y`` compounds the poses ``X`` and ``Y``
 |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
 |
 |      ==============   ==============   ===========  ======================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ======================
 |      Pose             Pose             Pose         matrix product
 |      Pose             scalar           NxN matrix   element-wise product
 |      scalar           Pose             NxN matrix   element-wise product
 |      Pose             N-vector         N-vector     vector transform
 |      Pose             NxM matrix       NxM matrix   transform each column
 |      ==============   ==============   ===========  ======================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar x Pose is handled by __rmul__`
 |          #. Scalar multiplication is commutative but the result is not a group
 |             operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
 |          SE3(array([[0., 0., 1., 0.],
 |                  [1., 0., 0., 0.],
 |                  [0., 1., 0., 0.],
 |                  [0., 0., 0., 1.]]))
 |          >>> SE3.Rx(pi/2) * 2
 |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
 |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
 |
 |      For vector transformation there are three cases:
 |
 |      =========  ===========  =====  ==========================
 |            Multiplicands             Product
 |      ----------------------  ---------------------------------
 |      len(left)  right.shape  shape  operation
 |      =========  ===========  =====  ==========================
 |      1          (N,)         (N,)   vector transformation
 |      M          (N,)         (N,M)  vector transformations
 |      1          (N,M)        (N,M)  column transformation
 |      =========  ===========  =====  ==========================
 |
 |      .. note::
 |          - The vector is an array-like, a 1D NumPy array or a list/tuple
 |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
 |            form, transformed, then converted back to Euclidean form.
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * [0, 1, 0]
 |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
 |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
 |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :return: Inequality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for inequality
 |
 |      - ``X != Y`` is true of the poses are of the same type but not numerically
 |        equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the inequality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``ne = left != right``
 |       1          M             M    ``ne[i] = left != right[i]``
 |       N          1             M    ``ne[i] = left[i] != right``
 |       M          M             M    ``ne[i] = left[i] != right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __pow__(self, n: 'int') -> 'Self'
 |      Overloaded ``**`` operator (superclass method)
 |
 |      :param n: exponent
 |      :type n: int
 |      :return: pose to the power ``n``
 |      :rtype: pose instance
 |
 |      ``X**n`` raise all values held in `X` to the specified power using repeated
 |      multiplication.  If ``n`` < 0 then the result is inverted.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.1) ** 2
 |          >>> SE3.Rx([0, 0.1]) ** 2
 |
 |  __radd__(right, left)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__add__`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> repr(x)
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Left-multiplication
 |
 |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
 |        elements of ``X`` by ``s`` and the result is a NumPy array.
 |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
 |        of ``A`` and ``X`` and the result is a NumPy array.
 |
 |      :seealso: :func:`__mul__`
 |
 |  __rsub__(right, left: 'Self')
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__sub__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of pose (superclass method)
 |
 |      :return: readable representation of the pose
 |      :rtype: str
 |
 |      Convert the pose's matrix value to a simple grid of numbers.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x)
 |
 |      Notes:
 |
 |          - By default, the output is colorised for an ANSI terminal console:
 |
 |              * red: rotational elements
 |              * blue: translational elements
 |              * white: constant elements
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Subtract elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
 |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
 |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ==============================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ==============================
 |      Pose             Pose             NxN matrix   element-wise matrix difference
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ==============================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar - Pose is handled by :meth:`__rsub__`
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose subtraction either or both operands may hold more than one value which
 |      results in the difference holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``diff = left - right``
 |       1          M             M    ``diff[i] = left - right[i]``
 |       N          1             M    ``diff[i] = left[i] - right``
 |       M          M             M    ``diff[i] = left[i]  right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __truediv__(left, right)
 |      Overloaded ``/`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      Pose composition or scaling:
 |
 |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
 |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
 |
 |      ==============   ==============   ===========  =========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   --------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  =========================
 |      Pose             Pose             Pose         matrix product by inverse
 |      Pose             scalar           NxN matrix   element-wise division
 |      ==============   ==============   ===========  =========================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar multiplication is not a group operation so the result will
 |             be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |  animate(self, *args, start=None, **kwargs) -> 'None'
 |      Plot pose object as an animated coordinate frame (superclass method)
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: same as ``self``
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
 |        from the origin in either 2D or 3D.  There are many options, see the
 |        links below.
 |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
 |        frame moving from pose ``X1``, in either 2D or 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=SE3.Ry(0.2))
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
 |
 |  conjugation(self, A: 'NDArray') -> 'NDArray'
 |      Matrix conjugation
 |
 |      :param A: matrix to conjugate
 |      :type A: ndarray
 |      :return: conjugated matrix
 |      :rtype: ndarray
 |
 |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
 |      is the current object.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO2
 |          >>> import numpy as np
 |          >>> R = SO2(0.5)
 |          >>> A = np.array([[10, 0], [0, 1]])
 |          >>> print(R * A * R.inv())
 |          >>> print(R.conjugation(A))
 |
 |  det(self) -> 'Tuple[float, Rn]'
 |      Determinant of rotational component (superclass method)
 |
 |      :return: Determinant of rotational component
 |      :rtype: float or NumPy array
 |
 |      ``x.det()`` is the determinant of the rotation component of the values
 |      of ``x``.
 |
 |      Example::
 |
 |          >>> x=SE3.Rand()
 |          >>> x.det()
 |          1.0000000000000004
 |          >>> x=SE3.Rand(N=2)
 |          >>> x.det()
 |          [0.9999999999999997, 1.0000000000000002]
 |
 |      :SymPy: not supported
 |
 |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
 |      Interpolate between poses (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :param shortest: take the shortest path along the great circle for the rotation
 |      :type shortest: bool, default to True
 |      :return: interpolated pose
 |      :rtype: same as ``self``
 |
 |      - ``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.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
 |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
 |          >>> x.interp(y, 0)    # this is x
 |          >>> x.interp(y, 1)    # this is y
 |          >>> x.interp(y, 0.5)  # this is in between
 |          >>> z = x.interp(y, 11)  # in 11 steps
 |          >>> len(z)
 |          >>> z[0]              # this is x
 |          >>> z[5]              # this is in between
 |
 |      .. note::
 |
 |          - 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
 |
 |  interp1(self, s: 'float' = None) -> 'Self'
 |      Interpolate pose (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1
 |      :type s: array_like
 |      :return: interpolated pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
 |
 |          ======  ======  ===========  ===============================
 |          len(X)  len(s)  len(result)  Result
 |          ======  ======  ===========  ===============================
 |          1       1       1            Y = interp(X, s)
 |          M       1       M            Y[i] = interp(X[i], s)
 |          1       M       M            Y[i] = interp(X, s[i])
 |          ======  ======  ===========  ===============================
 |
 |      Example::
 |
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x.interp(0))
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |          >>> print(x.interp(1))
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
 |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |          >>> y = x.interp(x, np.linspace(0, 1, 10))
 |          >>> len(y)
 |          10
 |          >>> y[5]
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
 |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |
 |      Notes:
 |
 |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
 |
 |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
 |
 |      :SymPy: not supported
 |
 |  ishom(self) -> 'bool'
 |      Test if object belongs to SE(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          True
 |
 |  ishom2(self) -> 'bool'
 |      Test if object belongs to SE(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          True
 |
 |  isrot(self) -> 'bool'
 |      Test if object belongs to SO(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          False
 |
 |  isrot2(self) -> 'bool'
 |      Test if object belongs to SO(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          False
 |
 |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
 |      Logarithm of pose (superclass method)
 |
 |      :return: logarithm
 |      :rtype: ndarray
 |      :raises: ValueError
 |
 |      An efficient closed-form solution of the matrix logarithm.
 |
 |      =====  ======  ===============================
 |      Input         Output
 |      -----  ---------------------------------------
 |      Pose   Shape   Structure
 |      =====  ======  ===============================
 |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
 |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
 |      =====  ======  ===============================
 |
 |      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. ]])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
 |      :func:`~spatialmath.base.transforms3d.trlog`
 |
 |      :SymPy: not supported
 |
 |  norm(self) -> 'Self'
 |      Normalize pose (superclass method)
 |
 |      :return: pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
 |        part of all values has been adjusted to ensure it is a proper orthogonal
 |        matrix rotation.
 |
 |      Example::
 |
 |          >>> x = SE3()
 |          >>> y = x.norm()
 |          >>> y
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |
 |      Notes:
 |
 |      #. Only the direction of A vector (the z-axis) is unchanged.
 |      #. Used to prevent finite word length arithmetic causing transforms to
 |         become 'unnormalized'.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
 |
 |  plot(self, *args, **kwargs) -> 'None'
 |      Plot pose object as a coordinate frame (superclass method)
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
 |        2D or 3D.  There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.plot(frame='A', color='green')
 |
 |      .. plot::
 |
 |          from spatialmath import SE3
 |          X = SE3.Rx(0.3)
 |          X.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
 |
 |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
 |      Print pose as a matrix (superclass method)
 |
 |      :param label: label to print before the matrix, defaults to None
 |      :type label: str, optional
 |      :param file: file to write to, defaults to None
 |      :type file: file object, optional
 |
 |      Print the pose as a matrix, with an optional line beforehand.  By default
 |      the matrix is printed to stdout.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3().print()
 |          >>> SE3().print("pose is:")
 |
 |      :seealso: :meth:`printline` :meth:`strline`
 |
 |  printline(self, *args, **kwargs) -> 'None'
 |      Print pose in compact single line format (superclass method)
 |
 |      :param arg: value for orient option, optional
 |      :type arg: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param file: file to write formatted string to. [default, stdout]
 |      :type file: file object
 |
 |      Print pose in a compact single line format. If ``X`` has multiple
 |      values, print one per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.printline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.printline()
 |          >>> x.printline('angvec')
 |          >>> x.printline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.printline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
 |
 |  prod(self, norm=False, check=True) -> 'Self'
 |      Product of elements (superclass method)
 |
 |      :param norm: normalize the product, defaults to False
 |      :type norm: bool, optional
 |      :param check: check that computed matrix is valid member of group, default True
 |      :bool check: bool, optional
 |      :return: Product of elements
 |      :rtype: pose instance
 |
 |      ``x.prod()`` is the product of the values held by ``x``, ie.
 |      :math:`\prod_i^N T_i`.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
 |          >>> x.prod()
 |
 |      .. note:: When compounding many transformations the product may become
 |          denormalized resulting in a result that is not a proper member of the
 |          group.  You can either disable membership checking by ``check=False``
 |          which is risky, or normalize the result by ``norm=True``.
 |
 |  simplify(self) -> 'Self'
 |      Symbolically simplify matrix values (superclass method)
 |
 |      :return: pose with symbolic elements
 |      :rtype: pose instance
 |
 |      Apply symbolic simplification to every element of every value in the
 |      pose instance.
 |
 |      Example::
 |
 |          >>> a = SE3.Rx(sympy.symbols('theta'))
 |          >>> b = a * a
 |          >>> b
 |          SE3(array([[1, 0, 0, 0.0],
 |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
 |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
 |          [0.0, 0, 0, 1.0]], dtype=object)
 |          >>> b.simplify()
 |          SE3(array([[1, 0, 0, 0],
 |          [0, cos(2*theta), -sin(2*theta), 0],
 |          [0, sin(2*theta), cos(2*theta), 0],
 |          [0, 0, 0, 1.00000000000000]], dtype=object))
 |
 |      .. todo:: No need to simplify the constants in bottom row
 |
 |      :SymPy: supported
 |
 |  stack(self) -> 'NDArray'
 |      Convert to 3-dimensional matrix
 |
 |      :return: 3-dimensional NumPy array
 |      :rtype: ndarray(n,n,m)
 |
 |      Converts the value to a 3-dimensional NumPy array where the values are
 |      stacked along the third axis.  The first two dimensions are given by
 |      ``self.shape``.
 |
 |  strline(self, *args, **kwargs) -> 'str'
 |      Convert pose to compact single line string (superclass method)
 |
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: pose in string format
 |      :rtype: str
 |
 |      Convert pose in a compact single line format. If ``X`` has multiple
 |      values, the string has one pose per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.strline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.strline()
 |          >>> x.strline('angvec')
 |          >>> x.strline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.strline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
 |
 |  ----------------------------------------------------------------------
 |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __new__(cls, *args, **kwargs)
 |      Create the subclass instance (superclass method)
 |
 |      Create a new instance and call the superclass initializer to enable the
 |      ``UserList`` capabilities.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  N
 |      Dimension of the object's group (superclass property)
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
 |      This corresponds to the dimension of the space, 2D or 3D, to which these
 |      rotations or rigid-body motions apply.
 |
 |      Example::
 |
 |          >>> SE3().N
 |          3
 |          >>> SE2().N
 |          2
 |
 |  about
 |      Succinct summary of object type and length (superclass property)
 |
 |      :return: succinct summary
 |      :rtype: str
 |
 |      Displays the type and the number of elements in compact form, for
 |      example::
 |
 |          >>> x = SE3([SE3() for i in range(20)])
 |          >>> len(x)
 |          20
 |          >>> print(x.about)
 |          SE3[20]
 |
 |  isSE
 |      Test if object belongs to SE(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SE2 or SE3
 |      :rtype: bool
 |
 |  isSO
 |      Test if object belongs to SO(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SO2 or SO3
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __len__(self)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SO2
Python Library Documentation: class SO2 in module spatialmath.pose2d

class SO2(spatialmath.baseposematrix.BasePoseMatrix)
 |  SO2(arg=None, *, unit='rad', check=True)
 |
 |  SO(2) matrix class
 |
 |  This subclass represents rotations in 2D space.  Internally it is a 2x2 orthogonal matrix belonging
 |  to the group SO(2).
 |
 |  .. inheritance-diagram:: spatialmath.pose2d.SO2
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  Method resolution order:
 |      SO2
 |      spatialmath.baseposematrix.BasePoseMatrix
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  SE2(self)
 |      Create SE(2) from SO(2)
 |
 |      :return: SE(2) with same rotation but zero translation
 |      :rtype: SE2 instance
 |
 |  __init__(self, arg=None, *, unit='rad', check=True)
 |      Construct new SO(2) object
 |
 |      :param unit: angular units 'deg' or 'rad' [default] if applicable
 |      :type unit: str, optional
 |      :param check: check for valid SO(2) elements if applicable, default to True
 |      :type check: bool
 |      :return: SO(2) rotation
 |      :rtype: SO2 instance
 |
 |      - ``SO2()`` is an SO2 instance representing a null rotation -- the identity matrix.
 |      - ``SO2(θ)`` is an SO2 instance representing a rotation by ``θ`` radians.  If ``θ`` is array_like
 |        `[θ1, θ2, ... θN]` then an SO2 instance containing a sequence of N rotations.
 |      - ``SO2(θ, unit='deg')`` is an SO2 instance representing a rotation by ``θ`` degrees.  If ``θ`` is array_like
 |        `[θ1, θ2, ... θN]` then an SO2 instance containing a sequence of N rotations.
 |      - ``SO2(R)`` is an SO2 instance with rotation described by the SO(2) matrix R which is a 2x2 numpy array.  If ``check``
 |        is ``True`` check the matrix belongs to SO(2).
 |      - ``SO2([R1, R2, ... RN])`` is an SO2 instance containing a sequence of N rotations, each described by an SO(2) matrix
 |        Ri which is a 2x2 numpy array. If ``check`` is ``True`` then check each matrix belongs to SO(2).
 |      - ``SO2([X1, X2, ... XN])`` is an SO2 instance containing a sequence of N rotations, where each Xi is an SO2 instance.
 |
 |  inv(self)
 |      Inverse of SO(2)
 |
 |      :return: inverse rotation
 |      :rtype: SO2 instance
 |
 |      - ``x.inv()`` is the inverse of `x`.
 |
 |      Notes:
 |
 |          - for elements of SO(2) this is the transpose.
 |          - if `x` contains a sequence, returns an `SO2` with a sequence of inverses
 |
 |  theta(self, unit='rad')
 |      SO(2) as a rotation angle
 |
 |      :param unit: angular units 'deg' or 'rad' [default]
 |      :type unit: str, optional
 |      :return: rotation angle
 |      :rtype: float or list
 |
 |      ``x.theta`` is the rotation angle such that `x` is `SO2(x.theta)`.
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  Exp(S, check=True)
 |      Construct new SO(2) rotation matrix from so(2) Lie algebra
 |
 |      :param S: element of Lie algebra so(2)
 |      :type S: numpy ndarray
 |      :param check: check that passed matrix is valid so(2), default True
 |      :type check: bool
 |      :return: SO(2) rotation matrix
 |      :rtype: SO2 instance
 |
 |      - ``SO2.Exp(S)`` is an SO(2) rotation defined by its Lie algebra
 |        which is a 2x2 so(2) matrix (skew symmetric)
 |
 |      :seealso: :func:`spatialmath.base.transforms2d.trexp`, :func:`spatialmath.base.transformsNd.skew`
 |
 |  Rand(N=1, arange=(0, 6.283185307179586), unit='rad')
 |      Construct new SO(2) with random rotation
 |
 |      :param arange: rotation range, defaults to :math:`[0, 2\pi)`.
 |      :type arange: 2-element array-like, optional
 |      :param unit: angular units as 'deg or 'rad' [default]
 |      :type unit: str, optional
 |      :param N: number of random rotations, defaults to 1
 |      :type N: int
 |      :return: SO(2) rotation matrix
 |      :rtype: SO2 instance
 |
 |      - ``SO2.Rand()`` is a random SO(2) rotation.
 |      - ``SO2.Rand([-90, 90], unit='deg')`` is a random SO(2) rotation between
 |        -90 and +90 degrees.
 |      - ``SO2.Rand(N)`` is a sequence of N random rotations.
 |
 |      Rotations are uniform over the specified interval.
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x, check=True)
 |      Test if matrix is valid SO(2)
 |
 |      :param x: matrix to test
 |      :type x: numpy.ndarray
 |      :return: True if the matrix is a valid element of SO(2), ie. it is a 2x2
 |          orthonormal matrix with determinant of +1.
 |      :rtype: bool
 |
 |      :seealso: :func:`~spatialmath.base.transform3d.isrot`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  R
 |      SO(2) or SE(2) as rotation matrix
 |
 |      :return: rotational component
 |      :rtype: numpy.ndarray, shape=(2,2)
 |
 |      ``x.R`` returns the rotation matrix, when `x` is `SO2` or `SE2`. If `len(x)` is:
 |
 |      - 1, return an ndarray with shape=(2,2)
 |      - N>1, return ndarray with shape=(N,2,2)
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (2,2)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __add__(left, right)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Add the elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
 |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
 |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ========================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ========================
 |      Pose             Pose             NxN matrix   element-wise matrix sum
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ========================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar + Pose is handled by :meth:`__radd__`
 |          #. Addition is commutative
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose addition either or both operands may hold more than one value which
 |      results in the sum holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``sum = left + right``
 |       1          M             M    ``sum[i] = left + right[i]``
 |       N          1             M    ``sum[i] = left[i] + right``
 |       M          M             M    ``sum[i] = left[i] + right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __eq__(left, right: 'Self') -> 'bool'
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for equality
 |
 |      ``X == Y`` is true of the poses are of the same type and numerically
 |      equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the equality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``eq = left == right``
 |       1          M             M    ``eq[i] = left == right[i]``
 |       N          1             M    ``eq[i] = left[i] == right``
 |       M          M             M    ``eq[i] = left[i] == right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __iadd__(left, right)
 |      Overloaded ``+=`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
 |      - ``X += s`` elementwise addition of the matrix elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__add__``
 |
 |  __imul__(left, right)
 |      Overloaded ``*=`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
 |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__mul__``
 |
 |  __isub__(left, right: 'Self')
 |      Overloaded ``-=`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises: ValueError
 |
 |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
 |        and ``Y`` and places the result in ``X``
 |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
 |        and the scalar ``s`` and places the result in ``X``
 |
 |      :seealso: ``__sub__``
 |
 |  __itruediv__(left, right)
 |      Overloaded ``/=`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
 |      - ``X /= s`` performs elementwise division of the elements of ``X``
 |        by ``s`` and places the result in ``X``
 |
 |      :seealso: ``__truediv__``
 |
 |  __matmul__(left, right)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :return: Product of two operands with normalization
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
 |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
 |        and places the result in ``X``
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally
 |          update over many cycles.
 |
 |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Pose composition, scaling or vector transformation:
 |
 |      - ``X * Y`` compounds the poses ``X`` and ``Y``
 |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
 |
 |      ==============   ==============   ===========  ======================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ======================
 |      Pose             Pose             Pose         matrix product
 |      Pose             scalar           NxN matrix   element-wise product
 |      scalar           Pose             NxN matrix   element-wise product
 |      Pose             N-vector         N-vector     vector transform
 |      Pose             NxM matrix       NxM matrix   transform each column
 |      ==============   ==============   ===========  ======================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar x Pose is handled by __rmul__`
 |          #. Scalar multiplication is commutative but the result is not a group
 |             operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
 |          SE3(array([[0., 0., 1., 0.],
 |                  [1., 0., 0., 0.],
 |                  [0., 1., 0., 0.],
 |                  [0., 0., 0., 1.]]))
 |          >>> SE3.Rx(pi/2) * 2
 |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
 |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
 |
 |      For vector transformation there are three cases:
 |
 |      =========  ===========  =====  ==========================
 |            Multiplicands             Product
 |      ----------------------  ---------------------------------
 |      len(left)  right.shape  shape  operation
 |      =========  ===========  =====  ==========================
 |      1          (N,)         (N,)   vector transformation
 |      M          (N,)         (N,M)  vector transformations
 |      1          (N,M)        (N,M)  column transformation
 |      =========  ===========  =====  ==========================
 |
 |      .. note::
 |          - The vector is an array-like, a 1D NumPy array or a list/tuple
 |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
 |            form, transformed, then converted back to Euclidean form.
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * [0, 1, 0]
 |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
 |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
 |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :return: Inequality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for inequality
 |
 |      - ``X != Y`` is true of the poses are of the same type but not numerically
 |        equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the inequality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``ne = left != right``
 |       1          M             M    ``ne[i] = left != right[i]``
 |       N          1             M    ``ne[i] = left[i] != right``
 |       M          M             M    ``ne[i] = left[i] != right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __pow__(self, n: 'int') -> 'Self'
 |      Overloaded ``**`` operator (superclass method)
 |
 |      :param n: exponent
 |      :type n: int
 |      :return: pose to the power ``n``
 |      :rtype: pose instance
 |
 |      ``X**n`` raise all values held in `X` to the specified power using repeated
 |      multiplication.  If ``n`` < 0 then the result is inverted.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.1) ** 2
 |          >>> SE3.Rx([0, 0.1]) ** 2
 |
 |  __radd__(right, left)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__add__`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> repr(x)
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Left-multiplication
 |
 |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
 |        elements of ``X`` by ``s`` and the result is a NumPy array.
 |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
 |        of ``A`` and ``X`` and the result is a NumPy array.
 |
 |      :seealso: :func:`__mul__`
 |
 |  __rsub__(right, left: 'Self')
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__sub__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of pose (superclass method)
 |
 |      :return: readable representation of the pose
 |      :rtype: str
 |
 |      Convert the pose's matrix value to a simple grid of numbers.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x)
 |
 |      Notes:
 |
 |          - By default, the output is colorised for an ANSI terminal console:
 |
 |              * red: rotational elements
 |              * blue: translational elements
 |              * white: constant elements
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Subtract elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
 |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
 |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ==============================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ==============================
 |      Pose             Pose             NxN matrix   element-wise matrix difference
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ==============================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar - Pose is handled by :meth:`__rsub__`
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose subtraction either or both operands may hold more than one value which
 |      results in the difference holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``diff = left - right``
 |       1          M             M    ``diff[i] = left - right[i]``
 |       N          1             M    ``diff[i] = left[i] - right``
 |       M          M             M    ``diff[i] = left[i]  right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __truediv__(left, right)
 |      Overloaded ``/`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      Pose composition or scaling:
 |
 |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
 |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
 |
 |      ==============   ==============   ===========  =========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   --------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  =========================
 |      Pose             Pose             Pose         matrix product by inverse
 |      Pose             scalar           NxN matrix   element-wise division
 |      ==============   ==============   ===========  =========================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar multiplication is not a group operation so the result will
 |             be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |  animate(self, *args, start=None, **kwargs) -> 'None'
 |      Plot pose object as an animated coordinate frame (superclass method)
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: same as ``self``
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
 |        from the origin in either 2D or 3D.  There are many options, see the
 |        links below.
 |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
 |        frame moving from pose ``X1``, in either 2D or 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=SE3.Ry(0.2))
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
 |
 |  conjugation(self, A: 'NDArray') -> 'NDArray'
 |      Matrix conjugation
 |
 |      :param A: matrix to conjugate
 |      :type A: ndarray
 |      :return: conjugated matrix
 |      :rtype: ndarray
 |
 |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
 |      is the current object.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO2
 |          >>> import numpy as np
 |          >>> R = SO2(0.5)
 |          >>> A = np.array([[10, 0], [0, 1]])
 |          >>> print(R * A * R.inv())
 |          >>> print(R.conjugation(A))
 |
 |  det(self) -> 'Tuple[float, Rn]'
 |      Determinant of rotational component (superclass method)
 |
 |      :return: Determinant of rotational component
 |      :rtype: float or NumPy array
 |
 |      ``x.det()`` is the determinant of the rotation component of the values
 |      of ``x``.
 |
 |      Example::
 |
 |          >>> x=SE3.Rand()
 |          >>> x.det()
 |          1.0000000000000004
 |          >>> x=SE3.Rand(N=2)
 |          >>> x.det()
 |          [0.9999999999999997, 1.0000000000000002]
 |
 |      :SymPy: not supported
 |
 |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
 |      Interpolate between poses (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :param shortest: take the shortest path along the great circle for the rotation
 |      :type shortest: bool, default to True
 |      :return: interpolated pose
 |      :rtype: same as ``self``
 |
 |      - ``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.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
 |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
 |          >>> x.interp(y, 0)    # this is x
 |          >>> x.interp(y, 1)    # this is y
 |          >>> x.interp(y, 0.5)  # this is in between
 |          >>> z = x.interp(y, 11)  # in 11 steps
 |          >>> len(z)
 |          >>> z[0]              # this is x
 |          >>> z[5]              # this is in between
 |
 |      .. note::
 |
 |          - 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
 |
 |  interp1(self, s: 'float' = None) -> 'Self'
 |      Interpolate pose (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1
 |      :type s: array_like
 |      :return: interpolated pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
 |
 |          ======  ======  ===========  ===============================
 |          len(X)  len(s)  len(result)  Result
 |          ======  ======  ===========  ===============================
 |          1       1       1            Y = interp(X, s)
 |          M       1       M            Y[i] = interp(X[i], s)
 |          1       M       M            Y[i] = interp(X, s[i])
 |          ======  ======  ===========  ===============================
 |
 |      Example::
 |
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x.interp(0))
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |          >>> print(x.interp(1))
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
 |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |          >>> y = x.interp(x, np.linspace(0, 1, 10))
 |          >>> len(y)
 |          10
 |          >>> y[5]
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
 |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |
 |      Notes:
 |
 |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
 |
 |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
 |
 |      :SymPy: not supported
 |
 |  ishom(self) -> 'bool'
 |      Test if object belongs to SE(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          True
 |
 |  ishom2(self) -> 'bool'
 |      Test if object belongs to SE(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          True
 |
 |  isrot(self) -> 'bool'
 |      Test if object belongs to SO(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          False
 |
 |  isrot2(self) -> 'bool'
 |      Test if object belongs to SO(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          False
 |
 |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
 |      Logarithm of pose (superclass method)
 |
 |      :return: logarithm
 |      :rtype: ndarray
 |      :raises: ValueError
 |
 |      An efficient closed-form solution of the matrix logarithm.
 |
 |      =====  ======  ===============================
 |      Input         Output
 |      -----  ---------------------------------------
 |      Pose   Shape   Structure
 |      =====  ======  ===============================
 |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
 |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
 |      =====  ======  ===============================
 |
 |      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. ]])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
 |      :func:`~spatialmath.base.transforms3d.trlog`
 |
 |      :SymPy: not supported
 |
 |  norm(self) -> 'Self'
 |      Normalize pose (superclass method)
 |
 |      :return: pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
 |        part of all values has been adjusted to ensure it is a proper orthogonal
 |        matrix rotation.
 |
 |      Example::
 |
 |          >>> x = SE3()
 |          >>> y = x.norm()
 |          >>> y
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |
 |      Notes:
 |
 |      #. Only the direction of A vector (the z-axis) is unchanged.
 |      #. Used to prevent finite word length arithmetic causing transforms to
 |         become 'unnormalized'.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
 |
 |  plot(self, *args, **kwargs) -> 'None'
 |      Plot pose object as a coordinate frame (superclass method)
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
 |        2D or 3D.  There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.plot(frame='A', color='green')
 |
 |      .. plot::
 |
 |          from spatialmath import SE3
 |          X = SE3.Rx(0.3)
 |          X.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
 |
 |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
 |      Print pose as a matrix (superclass method)
 |
 |      :param label: label to print before the matrix, defaults to None
 |      :type label: str, optional
 |      :param file: file to write to, defaults to None
 |      :type file: file object, optional
 |
 |      Print the pose as a matrix, with an optional line beforehand.  By default
 |      the matrix is printed to stdout.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3().print()
 |          >>> SE3().print("pose is:")
 |
 |      :seealso: :meth:`printline` :meth:`strline`
 |
 |  printline(self, *args, **kwargs) -> 'None'
 |      Print pose in compact single line format (superclass method)
 |
 |      :param arg: value for orient option, optional
 |      :type arg: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param file: file to write formatted string to. [default, stdout]
 |      :type file: file object
 |
 |      Print pose in a compact single line format. If ``X`` has multiple
 |      values, print one per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.printline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.printline()
 |          >>> x.printline('angvec')
 |          >>> x.printline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.printline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
 |
 |  prod(self, norm=False, check=True) -> 'Self'
 |      Product of elements (superclass method)
 |
 |      :param norm: normalize the product, defaults to False
 |      :type norm: bool, optional
 |      :param check: check that computed matrix is valid member of group, default True
 |      :bool check: bool, optional
 |      :return: Product of elements
 |      :rtype: pose instance
 |
 |      ``x.prod()`` is the product of the values held by ``x``, ie.
 |      :math:`\prod_i^N T_i`.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
 |          >>> x.prod()
 |
 |      .. note:: When compounding many transformations the product may become
 |          denormalized resulting in a result that is not a proper member of the
 |          group.  You can either disable membership checking by ``check=False``
 |          which is risky, or normalize the result by ``norm=True``.
 |
 |  simplify(self) -> 'Self'
 |      Symbolically simplify matrix values (superclass method)
 |
 |      :return: pose with symbolic elements
 |      :rtype: pose instance
 |
 |      Apply symbolic simplification to every element of every value in the
 |      pose instance.
 |
 |      Example::
 |
 |          >>> a = SE3.Rx(sympy.symbols('theta'))
 |          >>> b = a * a
 |          >>> b
 |          SE3(array([[1, 0, 0, 0.0],
 |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
 |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
 |          [0.0, 0, 0, 1.0]], dtype=object)
 |          >>> b.simplify()
 |          SE3(array([[1, 0, 0, 0],
 |          [0, cos(2*theta), -sin(2*theta), 0],
 |          [0, sin(2*theta), cos(2*theta), 0],
 |          [0, 0, 0, 1.00000000000000]], dtype=object))
 |
 |      .. todo:: No need to simplify the constants in bottom row
 |
 |      :SymPy: supported
 |
 |  stack(self) -> 'NDArray'
 |      Convert to 3-dimensional matrix
 |
 |      :return: 3-dimensional NumPy array
 |      :rtype: ndarray(n,n,m)
 |
 |      Converts the value to a 3-dimensional NumPy array where the values are
 |      stacked along the third axis.  The first two dimensions are given by
 |      ``self.shape``.
 |
 |  strline(self, *args, **kwargs) -> 'str'
 |      Convert pose to compact single line string (superclass method)
 |
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: pose in string format
 |      :rtype: str
 |
 |      Convert pose in a compact single line format. If ``X`` has multiple
 |      values, the string has one pose per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.strline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.strline()
 |          >>> x.strline('angvec')
 |          >>> x.strline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.strline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
 |
 |  ----------------------------------------------------------------------
 |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __new__(cls, *args, **kwargs)
 |      Create the subclass instance (superclass method)
 |
 |      Create a new instance and call the superclass initializer to enable the
 |      ``UserList`` capabilities.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  N
 |      Dimension of the object's group (superclass property)
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
 |      This corresponds to the dimension of the space, 2D or 3D, to which these
 |      rotations or rigid-body motions apply.
 |
 |      Example::
 |
 |          >>> SE3().N
 |          3
 |          >>> SE2().N
 |          2
 |
 |  about
 |      Succinct summary of object type and length (superclass property)
 |
 |      :return: succinct summary
 |      :rtype: str
 |
 |      Displays the type and the number of elements in compact form, for
 |      example::
 |
 |          >>> x = SE3([SE3() for i in range(20)])
 |          >>> len(x)
 |          20
 |          >>> print(x.about)
 |          SE3[20]
 |
 |  isSE
 |      Test if object belongs to SE(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SE2 or SE3
 |      :rtype: bool
 |
 |  isSO
 |      Test if object belongs to SO(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SO2 or SO3
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __len__(self)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SO3
Python Library Documentation: class SO3 in module spatialmath.pose3d

class SO3(spatialmath.baseposematrix.BasePoseMatrix)
 |  SO3(arg=None, *, check=True)
 |
 |     SO(3) matrix class
 |
 |     This subclass represents rotations in 3D space.  Internally it is a 3x3
 |     orthogonal matrix belonging to the group SO(3).
 |
 |  .. inheritance-diagram:: spatialmath.pose3d.SO3
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  Method resolution order:
 |      SO3
 |      spatialmath.baseposematrix.BasePoseMatrix
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  UnitQuaternion(self) -> 'UnitQuaternion'
 |      SO3 as a unit quaternion instance
 |
 |      :return: a unit quaternion representation
 |      :rtype: UnitQuaternion instance
 |
 |      ``R.UnitQuaternion()`` is an ``UnitQuaternion`` instance representing the same rotation
 |      as the SO3 rotation ``R``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> SO3.Rz(0.3).UnitQuaternion()
 |
 |  __init__(self, arg=None, *, check=True)
 |      Construct new SO(3) object
 |
 |      :rtype: SO3 instance
 |
 |      There are multiple call signatures:
 |
 |      - ``SO3()`` is an ``SO3`` instance with one value -- a 3x3 identity
 |        matrix which corresponds to a null rotation
 |      - ``SO3(R)`` is an ``SO3`` instance with with the value ``R`` which is a
 |        3x3 numpy array representing an SO(3) rotation matrix.  If ``check``
 |        is ``True`` check the matrix belongs to SO(3).
 |      - ``SO3([R1, R2, ... RN])`` is an ``SO3`` instance wwith ``N`` values
 |        given by the elements ``Ri`` each of which is a 3x3 NumPy array
 |        representing an SO(3) matrix. If ``check`` is ``True`` check the
 |        matrix belongs to SO(3).
 |      - ``SO3([X1, X2, ... XN])`` is an ``SO3`` instance with ``N`` values
 |        given by the elements ``Xi`` each of which is an SO3 or SE3 instance.
 |
 |      :SymPy: supported
 |
 |  angdist(self, other: 'SO3', metric: 'int' = 6) -> 'Union[float, ndarray]'
 |      Angular distance metric between rotations
 |
 |      :param other: second rotation
 |      :type other: SO3 instance
 |      :param metric: metric, default is 6
 |      :type metric: int
 |      :raises TypeError: if other is not an SO3
 |      :return: angle in radians
 |      :rtype: float or ndarray
 |
 |      ``R1.angdist(R2)`` is the geodesic norm, or geodesic distance between two
 |      rotations.
 |
 |      Several metrics are supported, the first 5 are computed after conversion
 |      to unit quaternions.
 |
 |      ======   ===============================================================
 |      Metric   Details
 |      ======   ===============================================================
 |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
 |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      3        :math:`2 \tan^{-1} \| \q_1 - \q_2\| / \|\q_1 + \q_2\| \in [0, \pi/2]`
 |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
 |      5        :math:`\|I - \mat{R}_1 \mat{R}_2^T\| \in [0, 2]`
 |      6        :math:`\|\log \mat{R}_1 \mat{R}_2^T\| \in [0, \pi]`
 |      ======   ===============================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> R1 = SO3.Rx(0.3)
 |          >>> R2 = SO3.Ry(0.3)
 |          >>> print(R1.angdist(R1))
 |          >>> print(R1.angdist(R2))
 |
 |      .. note::
 |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
 |            numeric errors which push the argument of ``acos()`` marginally
 |            outside its domain [0, 1].
 |          - metrics 2 and 3 are equivalent, but 3 is more robust
 |
 |      :seealso: :func:`UnitQuaternion.angdist`
 |
 |  angvec(self, unit: 'str' = 'rad') -> 'Tuple[float, R3]'
 |      SO(3) or SE(3) as angle and rotation vector
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: :math:`(\theta, \hat{\bf v})`
 |      :rtype: float or ndarray(3)
 |
 |      ``x.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
 |      angle and a rotation axis.
 |
 |      By default the angle is in radians but can be changed setting `unit='deg'`.
 |
 |      .. note::
 |
 |          - If the input is SE(3) the translation component is ignored.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> R = SO3.Rx(0.3)
 |          >>> R.angvec()
 |
 |      :seealso: :meth:`eulervec` :meth:`AngVec` :meth:`~spatialmath.quaternion.UnitQuaternion.angvec` :meth:`~spatialmath.quaternion.AngVec`, :func:`~angvec2r`
 |
 |  eul(self, unit: 'str' = 'rad', flip: 'bool' = False) -> 'Union[R3, RNx3]'
 |      SO(3) or SE(3) as Euler angles
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of Euler angles
 |      :rtype: ndarray(3,), ndarray(n,3)
 |
 |      ``x.eul`` is the Euler angle representation of the rotation.  Euler angles are
 |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
 |      rotations about the Z, Y, Z axes respectively.
 |
 |      If ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(3,N)
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.tr2eul`
 |      :SymPy: not supported
 |
 |  eulervec(self) -> 'R3'
 |      SO(3) or SE(3) as Euler vector (exponential coordinates)
 |
 |      :return: :math:`\theta \hat{\bf v}`
 |      :rtype: ndarray(3)
 |
 |      ``x.eulervec()`` is the Euler vector (or exponential coordinates) which
 |      is related to angle-axis notation and is the product of the rotation
 |      angle and the rotation axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> R = SO3.Rx(0.3)
 |          >>> R.eulervec()
 |
 |      .. note::
 |
 |          - If the input is SE(3) the translation component is ignored.
 |
 |      :seealso: :meth:`angvec` :func:`~angvec2r`
 |
 |  inv(self) -> 'Self'
 |      Inverse of SO(3)
 |
 |      :return: inverse
 |      :rtype: SO2 instance
 |
 |      Efficiently compute the inverse of each of the SO(3) values taking into
 |      account the matrix structure.  For an SO(3) matrix the inverse is the
 |      transpose.
 |
 |  mean(self, tol: 'float' = 20) -> 'SO3'
 |      Mean of a set of SO(3) values
 |
 |      :param tol: iteration tolerance in units of eps, defaults to 20
 |      :type tol: float, optional
 |      :return: the mean rotation
 |      :rtype: :class:`SO3` instance.
 |
 |      Computes the Karcher mean of the set of SO(3) rotations within the :class:`SO3` instance.
 |
 |      :references:
 |          - `**Hartley, Trumpf** - "Rotation Averaging" - IJCV 2011 <https://users.cecs.anu.edu.au/~hartley/Papers/PDF/Hartley-Trumpf:Rotation-averaging:IJCV.pdf>`_, Algorithm 1, page 15.
 |          - `Karcher mean <https://en.wikipedia.org/wiki/Karcher_mean>`_
 |
 |      :seealso: :class:`SE3.mean`
 |
 |  rpy(self, unit: 'str' = 'rad', order: 'str' = 'zyx') -> 'Union[R3, RNx3]'
 |      SO(3) or SE(3) as roll-pitch-yaw angles
 |
 |      :param order: angle sequence order, default to 'zyx'
 |      :type order: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of roll-pitch-yaw angles
 |      :rtype: ndarray(3,), ndarray(n,3)
 |
 |      ``x.rpy`` is the roll-pitch-yaw angle representation of the rotation.  The angles are
 |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
 |      specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
 |            to the optic axis and x-axis parallel to the pixel rows.
 |
 |      If `len(x)` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(3,N)
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.RPY`, :func:`~spatialmath.base.transforms3d.tr2rpy`
 |      :SymPy: not supported
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  AngVec(theta, v, *, unit='rad') -> 'Self'
 |      Construct a new SO(3) rotation matrix from rotation angle and axis
 |
 |      :param theta: rotation
 |      :type theta: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param v: rotation axis, 3-vector
 |      :type v: array_like
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      ``SO3.AngVec(theta, V)`` is an SO(3) rotation defined by
 |      a rotation of ``THETA`` about the vector ``V``.
 |
 |      .. deprecated:: 0.9.8
 |          Use :meth:`AngleAxis` instead.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`spatialmath.base.transforms3d.angvec2r`
 |
 |  AngleAxis(theta: 'float', v: 'ArrayLike3', *, unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) rotation matrix from rotation angle and axis
 |
 |      :param theta: rotation
 |      :type theta: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param v: rotation axis, 3-vector
 |      :type v: array_like
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      ``SO3.AngleAxis(theta, V)`` is an SO(3) rotation defined by
 |      a rotation of ``THETA`` about the vector ``V``.
 |
 |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
 |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`spatialmath.base.transforms3d.angvec2r`
 |
 |  Eul(*angles, unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) from Euler angles
 |
 |      :param 𝚪: Euler angles
 |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      ``SO3.Eul(𝚪)`` is an SO(3) rotation defined by a 3-vector of Euler
 |        angles :math:`\Gamma = (\phi, \theta, \psi)` which correspond to
 |        consecutive rotations about the Z, Y, Z axes respectively. If ``𝚪``
 |        is an Nx3 matrix then the result is a sequence of rotations each
 |        defined by Euler angles corresponding to the rows of ``angles``.
 |
 |      ``SO3.Eul(φ, θ, ψ)`` as above but the angles are provided as three
 |        scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> SO3.Eul(0.1, 0.2, 0.3)
 |          >>> SO3.Eul([0.1, 0.2, 0.3])
 |          >>> SO3.Eul(10, 20, 30, unit="deg")
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.eul`, :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.eul2r`
 |
 |  EulerVec(w) -> 'Self'
 |      Construct a new SO(3) rotation matrix from an Euler rotation vector
 |
 |      :param ω: rotation axis
 |      :type ω: 3-element array_like
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      ``SO3.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
 |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
 |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> SO3.EulerVec([0.5,0,0])
 |
 |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
 |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  Exp(S: 'Union[R3, RNx3]', check: 'bool' = True, so3: 'bool' = True) -> 'Self'
 |      Create an SO(3) rotation matrix from so(3)
 |
 |      :param S: Lie algebra so(3)
 |      :type S: ndarray(3,3), ndarray(n,3)
 |      :param check: check that passed matrix is valid so(3), default True
 |      :bool check: bool, optional
 |      :param so3: the input is interpretted as an so(3) matrix not a stack of three twists, default True
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      - ``SO3.Exp(S)`` is an SO(3) rotation defined by its Lie algebra
 |        which is a 3x3 so(3) matrix (skew symmetric)
 |      - ``SO3.Exp(t)`` is an SO(3) rotation defined by a 3-element twist
 |        vector (the unique elements of the so(3) skew-symmetric matrix)
 |      - ``SO3.Exp(T)`` is a sequence of SO(3) rotations defined by an Nx3 matrix
 |        of twist vectors, one per row.
 |
 |      .. note::
 |      - if :math:`\theta \eq 0` the result in an identity matrix
 |      - an input 3x3 matrix is ambiguous, it could be the first or third case above.  In this
 |        case the parameter `so3` is the decider.
 |
 |      :seealso: :func:`spatialmath.base.transforms3d.trexp`, :func:`spatialmath.base.transformsNd.skew`
 |
 |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'Self'
 |      Construct a new SO(3) from two vectors
 |
 |      :param o: 3-vector parallel to Y- axis
 |      :type o: array_like
 |      :param a: 3-vector parallel to the Z-axis
 |      :type o: array_like
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      ``SO3.OA(O, A)`` is an SO(3) rotation defined in terms of
 |      vectors parallel to the Y- and Z-axes of its reference frame.  In robotics these axes are
 |      respectively called the *orientation* and *approach* vectors defined such that
 |      R = [N, O, A] and N = O x A.
 |
 |      .. note::
 |
 |          - Only the ``A`` vector is guaranteed to have the same direction in the resulting
 |          rotation matrix
 |          - ``O`` and ``A`` do not have to be unit-length, they are normalized
 |          - ``O`` and ``A` do not have to be orthogonal, so long as they are not parallel
 |
 |      :seealso: :func:`spatialmath.base.transforms3d.oa2r`
 |
 |  RPY(*angles, unit='rad', order='zyx')
 |      Construct a new SO(3) from roll-pitch-yaw angles
 |
 |      :param angles: roll-pitch-yaw angles
 |      :type angles: array_like(3), array_like(n,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
 |      :type order: str
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      - ``SO3.RPY(angles)`` is an SO(3) rotation defined by a 3-vector of
 |        roll, pitch, yaw angles :math:`(\alpha, \beta, \gamma)`. If ``angles``
 |        is an Nx3 matrix then the result is a sequence of rotations each
 |        defined by RPY angles corresponding to the rows of angles. The angles
 |        correspond to successive rotations about the axes specified by
 |        ``order``:
 |
 |           - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |             then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
 |             and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
 |            to the optic axis and x-axis parallel to the pixel rows.
 |
 |      - ``SO3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
 |        scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> SO3.RPY(0.1, 0.2, 0.3)
 |          >>> SO3.RPY([0.1, 0.2, 0.3])
 |          >>> SO3.RPY(0.1, 0.2, 0.3, order='xyz')
 |          >>> SO3.RPY(10, 20, 30, unit="deg")
 |
 |
 |      :seealso: :func:`~spatialmath.pose3d.SE3.rpy`, :func:`~spatialmath.pose3d.SE3.RPY`, :func:`spatialmath.base.transforms3d.rpy2r`
 |
 |  Rand(N: 'int' = 1, *, theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) from random rotation
 |
 |      :param N: number of random rotations
 |      :type N: int
 |      :param theta_range: angular magnitude range [min,max], defaults to None.
 |      :type xrange: 2-element sequence, optional
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SO(3) rotation matrix
 |      :rtype: SO3 instance
 |
 |      - ``SO3.Rand()`` is a random SO(3) rotation.
 |      - ``SO3.Rand(N)`` is a sequence of N random rotations.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> x = SO3.Rand()
 |          >>> x
 |
 |      :seealso: :func:`spatialmath.quaternion.UnitQuaternion.Rand`
 |
 |  RotatedVector(v1: 'ArrayLike3', v2: 'ArrayLike3', tol=20) -> 'Self'
 |      Construct a new SO(3) from a vector and its rotated image
 |
 |      :param v1: initial vector
 |      :type v1: array_like(3)
 |      :param v2: vector after rotation
 |      :type v2: array_like(3)
 |      :param tol: tolerance for singularity in units of eps, defaults to 20
 |      :type tol: float
 |      :return: SO(3) rotation
 |      :rtype: :class:`SO3` instance
 |
 |      ``SO3.RotatedVector(v1, v2)`` is an SO(3) rotation defined in terms of
 |      two vectors. The rotation takes vector ``v1`` to ``v2``.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> v1 = [1, 2, 3]
 |          >>> v2 = SO3.Eul(0.3, 0.4, 0.5) * v1
 |          >>> print(v2)
 |          >>> R = SO3.RotatedVector(v1, v2)
 |          >>> print(R)
 |          >>> print(R * v1)
 |
 |      .. note:: The vectors do not have to be unit-length.
 |
 |  Rx(theta: 'float', unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) from X-axis rotation
 |
 |      :param θ: rotation angle about the X-axis
 |      :type θ: float or array_like
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      - ``SE3.Rx(θ)`` is an SO(3) rotation of ``θ`` radians about the x-axis
 |      - ``SE3.Rx(θ, "deg")`` as above but ``θ`` is in degrees
 |
 |      If ``theta`` is an array then the result is a sequence of rotations defined by consecutive
 |      elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> import numpy as np
 |          >>> x = SO3.Rx(np.linspace(0, math.pi, 20))
 |          >>> len(x)
 |          >>> x[7]
 |
 |  Ry(theta, unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) from Y-axis rotation
 |
 |      :param θ: rotation angle about Y-axis
 |      :type θ: float or array_like
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      - ``SO3.Ry(θ)`` is an SO(3) rotation of ``θ`` radians about the y-axis
 |      - ``SO3.Ry(θ, "deg")`` as above but ``θ`` is in degrees
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined by consecutive
 |      elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> import numpy as np
 |          >>> x = SO3.Ry(np.linspace(0, math.pi, 20))
 |          >>> len(x)
 |          >>> x[7]
 |
 |  Rz(theta, unit: 'str' = 'rad') -> 'Self'
 |      Construct a new SO(3) from Z-axis rotation
 |
 |      :param θ: rotation angle about Z-axis
 |      :type θ: float or array_like
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: SO(3) rotation
 |      :rtype: SO3 instance
 |
 |      - ``SO3.Rz(θ)`` is an SO(3) rotation of ``θ`` radians about the z-axis
 |      - ``SO3.Rz(θ, "deg")`` as above but ``θ`` is in degrees
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined by consecutive
 |      elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> import numpy as np
 |          >>> x = SO3.Rz(np.linspace(0, math.pi, 20))
 |          >>> len(x)
 |          >>> x[7]
 |
 |  TwoVectors(x: 'Optional[Union[str, ArrayLike3]]' = None, y: 'Optional[Union[str, ArrayLike3]]' = None, z: 'Optional[Union[str, ArrayLike3]]' = None) -> 'Self'
 |      Construct a new SO(3) from any two vectors
 |
 |      :param x: new x-axis, defaults to None
 |      :type x: str, array_like(3), optional
 |      :param y: new y-axis, defaults to None
 |      :type y: str, array_like(3), optional
 |      :param z: new z-axis, defaults to None
 |      :type z: str, array_like(3), optional
 |
 |      Create a rotation by defining the direction of two of the new
 |      axes in terms of the old axes.  Axes are denoted by strings ``"x"``,
 |      ``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
 |
 |      The directions can also be specified by 3-element vectors. If the vectors are not orthogonal,
 |      they will orthogonalized w.r.t. the first available dimension. I.e. if x is available, it will be
 |      normalized and the remaining vector will be orthogonalized w.r.t. x, else, y will be normalized
 |      and z will be orthogonalized w.r.t. y.
 |
 |      To create a rotation where the new frame has its x-axis in -z-direction
 |      of the previous frame, and its z-axis in the x-direction of the previous
 |      frame is::
 |
 |          >>> SO3.TwoVectors(x='-z', z='x')
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x: 'NDArray', check: 'bool' = True) -> 'bool'
 |      Test if matrix is valid SO(3)
 |
 |      :param x: matrix to test
 |      :type x: numpy.ndarray
 |      :return: ``True`` if the matrix is a valid element of SO(3), ie. it is a 3x3
 |          orthonormal matrix with determinant of +1.
 |      :rtype: bool
 |
 |      :seealso: :func:`~spatialmath.base.transform3d.isrot`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  R
 |      SO(3) or SE(3) as rotation matrix
 |
 |      :return: rotational component
 |      :rtype: ndarray(3,3)
 |
 |      ``x.R`` is the rotation matrix component of ``x`` as an array with
 |      shape (3,3). If ``len(x) > 1``, return an array with shape=(N,3,3).
 |
 |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
 |          ``x[i]``. This is different to the MATLAB version where the i'th
 |          rotation matrix is ``x(:,:,i)``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO3
 |          >>> x = SO3.Rx(0.3)
 |          >>> x.R
 |
 |      :SymPy: supported
 |
 |  a
 |      Approach vector of SO(3) or SE(3)
 |
 |      :return: approach vector
 |      :rtype: ndarray(3)
 |
 |      This is the third column of the rotation submatrix, sometimes called the
 |      *approach vector*.  It is parallel to the z-axis of the frame defined by
 |      this pose.
 |
 |  n
 |      Normal vector of SO(3) or SE(3)
 |
 |      :return: normal vector
 |      :rtype: ndarray(3)
 |
 |      This is the first column of the rotation submatrix, sometimes called the
 |      *normal vector*.  It is parallel to the x-axis of the frame defined by
 |      this pose.
 |
 |  o
 |      Orientation vector of SO(3) or SE(3)
 |
 |      :return: orientation vector
 |      :rtype: ndarray(3)
 |
 |      This is the second column of the rotation submatrix, sometimes called
 |      the *orientation vector*.  It is parallel to the y-axis of the frame
 |      defined by this pose.
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (3,3)
 |      :rtype: tuple
 |
 |      Each value within the ``SO3`` instance is a NumPy array of this shape.
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __add__(left, right)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Add the elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
 |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
 |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ========================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ========================
 |      Pose             Pose             NxN matrix   element-wise matrix sum
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ========================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar + Pose is handled by :meth:`__radd__`
 |          #. Addition is commutative
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose addition either or both operands may hold more than one value which
 |      results in the sum holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``sum = left + right``
 |       1          M             M    ``sum[i] = left + right[i]``
 |       N          1             M    ``sum[i] = left[i] + right``
 |       M          M             M    ``sum[i] = left[i] + right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __eq__(left, right: 'Self') -> 'bool'
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for equality
 |
 |      ``X == Y`` is true of the poses are of the same type and numerically
 |      equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the equality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``eq = left == right``
 |       1          M             M    ``eq[i] = left == right[i]``
 |       N          1             M    ``eq[i] = left[i] == right``
 |       M          M             M    ``eq[i] = left[i] == right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __iadd__(left, right)
 |      Overloaded ``+=`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
 |      - ``X += s`` elementwise addition of the matrix elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__add__``
 |
 |  __imul__(left, right)
 |      Overloaded ``*=`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
 |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
 |        and ``s`` and places the result in ``X``
 |
 |      :seealso: ``__mul__``
 |
 |  __isub__(left, right: 'Self')
 |      Overloaded ``-=`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises: ValueError
 |
 |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
 |        and ``Y`` and places the result in ``X``
 |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
 |        and the scalar ``s`` and places the result in ``X``
 |
 |      :seealso: ``__sub__``
 |
 |  __itruediv__(left, right)
 |      Overloaded ``/=`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
 |      - ``X /= s`` performs elementwise division of the elements of ``X``
 |        by ``s`` and places the result in ``X``
 |
 |      :seealso: ``__truediv__``
 |
 |  __matmul__(left, right)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :return: Product of two operands with normalization
 |      :rtype: Pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
 |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
 |        and places the result in ``X``
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally
 |          update over many cycles.
 |
 |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Pose composition, scaling or vector transformation:
 |
 |      - ``X * Y`` compounds the poses ``X`` and ``Y``
 |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
 |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
 |
 |      ==============   ==============   ===========  ======================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ======================
 |      Pose             Pose             Pose         matrix product
 |      Pose             scalar           NxN matrix   element-wise product
 |      scalar           Pose             NxN matrix   element-wise product
 |      Pose             N-vector         N-vector     vector transform
 |      Pose             NxM matrix       NxM matrix   transform each column
 |      ==============   ==============   ===========  ======================
 |
 |      .. note::
 |
 |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar x Pose is handled by __rmul__`
 |          #. Scalar multiplication is commutative but the result is not a group
 |             operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
 |          SE3(array([[0., 0., 1., 0.],
 |                  [1., 0., 0., 0.],
 |                  [0., 1., 0., 0.],
 |                  [0., 0., 0., 1.]]))
 |          >>> SE3.Rx(pi/2) * 2
 |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
 |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
 |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
 |
 |      For vector transformation there are three cases:
 |
 |      =========  ===========  =====  ==========================
 |            Multiplicands             Product
 |      ----------------------  ---------------------------------
 |      len(left)  right.shape  shape  operation
 |      =========  ===========  =====  ==========================
 |      1          (N,)         (N,)   vector transformation
 |      M          (N,)         (N,M)  vector transformations
 |      1          (N,M)        (N,M)  column transformation
 |      =========  ===========  =====  ==========================
 |
 |      .. note::
 |          - The vector is an array-like, a 1D NumPy array or a list/tuple
 |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
 |            form, transformed, then converted back to Euclidean form.
 |
 |      Example::
 |
 |          >>> SE3.Rx(pi/2) * [0, 1, 0]
 |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
 |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
 |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :return: Inequality of two operands
 |      :rtype: bool or list of bool
 |
 |      Test two poses for inequality
 |
 |      - ``X != Y`` is true of the poses are of the same type but not numerically
 |        equal.
 |
 |      If either or both operands may hold more than one value which
 |      results in the inequality test holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``ne = left != right``
 |       1          M             M    ``ne[i] = left != right[i]``
 |       N          1             M    ``ne[i] = left[i] != right``
 |       M          M             M    ``ne[i] = left[i] != right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __pow__(self, n: 'int') -> 'Self'
 |      Overloaded ``**`` operator (superclass method)
 |
 |      :param n: exponent
 |      :type n: int
 |      :return: pose to the power ``n``
 |      :rtype: pose instance
 |
 |      ``X**n`` raise all values held in `X` to the specified power using repeated
 |      multiplication.  If ``n`` < 0 then the result is inverted.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3.Rx(0.1) ** 2
 |          >>> SE3.Rx([0, 0.1]) ** 2
 |
 |  __radd__(right, left)
 |      Overloaded ``+`` operator (superclass method)
 |
 |      :return: Sum of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__add__`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> repr(x)
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: Product of two operands
 |      :rtype: Pose instance or NumPy array
 |      :raises NotImplemented: for incompatible arguments
 |
 |      Left-multiplication
 |
 |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
 |        elements of ``X`` by ``s`` and the result is a NumPy array.
 |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
 |        of ``A`` and ``X`` and the result is a NumPy array.
 |
 |      :seealso: :func:`__mul__`
 |
 |  __rsub__(right, left: 'Self')
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |      Left-addition by a scalar
 |
 |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
 |
 |      :seealso: :meth:`__sub__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of pose (superclass method)
 |
 |      :return: readable representation of the pose
 |      :rtype: str
 |
 |      Convert the pose's matrix value to a simple grid of numbers.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x)
 |
 |      Notes:
 |
 |          - By default, the output is colorised for an ANSI terminal console:
 |
 |              * red: rotational elements
 |              * blue: translational elements
 |              * white: constant elements
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: Difference of two operands
 |      :rtype: NumPy array, shape=(N,N)
 |      :raises ValueError: for incompatible arguments
 |
 |
 |      Subtract elements of two poses.  This is not a group operation so the
 |      result is a matrix not a pose class.
 |
 |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
 |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
 |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
 |
 |      ==============   ==============   ===========  ==============================
 |                 Operands                   Sum
 |      -------------------------------   -------------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  ==============================
 |      Pose             Pose             NxN matrix   element-wise matrix difference
 |      Pose             scalar           NxN matrix   element-wise sum
 |      scalar           Pose             NxN matrix   element-wise sum
 |      ==============   ==============   ===========  ==============================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. scalar - Pose is handled by :meth:`__rsub__`
 |          #. Any other input combinations result in a ``ValueError``.
 |
 |      For pose subtraction either or both operands may hold more than one value which
 |      results in the difference holding more than one value according to:
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``diff = left - right``
 |       1          M             M    ``diff[i] = left - right[i]``
 |       N          1             M    ``diff[i] = left[i] - right``
 |       M          M             M    ``diff[i] = left[i]  right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __truediv__(left, right)
 |      Overloaded ``/`` operator (superclass method)
 |
 |      :return: Product of right operand and inverse of left operand
 |      :rtype: pose instance or NumPy array
 |      :raises ValueError: for incompatible arguments
 |
 |      Pose composition or scaling:
 |
 |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
 |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
 |
 |      ==============   ==============   ===========  =========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   --------------------------------------
 |          left             right            type           operation
 |      ==============   ==============   ===========  =========================
 |      Pose             Pose             Pose         matrix product by inverse
 |      Pose             scalar           NxN matrix   element-wise division
 |      ==============   ==============   ===========  =========================
 |
 |      .. note::
 |
 |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
 |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
 |          #. Scalar multiplication is not a group operation so the result will
 |             be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |  animate(self, *args, start=None, **kwargs) -> 'None'
 |      Plot pose object as an animated coordinate frame (superclass method)
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: same as ``self``
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
 |        from the origin in either 2D or 3D.  There are many options, see the
 |        links below.
 |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
 |        frame moving from pose ``X1``, in either 2D or 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=SE3.Ry(0.2))
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
 |
 |  conjugation(self, A: 'NDArray') -> 'NDArray'
 |      Matrix conjugation
 |
 |      :param A: matrix to conjugate
 |      :type A: ndarray
 |      :return: conjugated matrix
 |      :rtype: ndarray
 |
 |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
 |      is the current object.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SO2
 |          >>> import numpy as np
 |          >>> R = SO2(0.5)
 |          >>> A = np.array([[10, 0], [0, 1]])
 |          >>> print(R * A * R.inv())
 |          >>> print(R.conjugation(A))
 |
 |  det(self) -> 'Tuple[float, Rn]'
 |      Determinant of rotational component (superclass method)
 |
 |      :return: Determinant of rotational component
 |      :rtype: float or NumPy array
 |
 |      ``x.det()`` is the determinant of the rotation component of the values
 |      of ``x``.
 |
 |      Example::
 |
 |          >>> x=SE3.Rand()
 |          >>> x.det()
 |          1.0000000000000004
 |          >>> x=SE3.Rand(N=2)
 |          >>> x.det()
 |          [0.9999999999999997, 1.0000000000000002]
 |
 |      :SymPy: not supported
 |
 |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
 |      Interpolate between poses (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :param shortest: take the shortest path along the great circle for the rotation
 |      :type shortest: bool, default to True
 |      :return: interpolated pose
 |      :rtype: same as ``self``
 |
 |      - ``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.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
 |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
 |          >>> x.interp(y, 0)    # this is x
 |          >>> x.interp(y, 1)    # this is y
 |          >>> x.interp(y, 0.5)  # this is in between
 |          >>> z = x.interp(y, 11)  # in 11 steps
 |          >>> len(z)
 |          >>> z[0]              # this is x
 |          >>> z[5]              # this is in between
 |
 |      .. note::
 |
 |          - 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
 |
 |  interp1(self, s: 'float' = None) -> 'Self'
 |      Interpolate pose (superclass method)
 |
 |      :param end: final pose
 |      :type end: same as ``self``
 |      :param s: interpolation coefficient, range 0 to 1
 |      :type s: array_like
 |      :return: interpolated pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
 |
 |          ======  ======  ===========  ===============================
 |          len(X)  len(s)  len(result)  Result
 |          ======  ======  ===========  ===============================
 |          1       1       1            Y = interp(X, s)
 |          M       1       M            Y[i] = interp(X[i], s)
 |          1       M       M            Y[i] = interp(X, s[i])
 |          ======  ======  ===========  ===============================
 |
 |      Example::
 |
 |          >>> x = SE3.Rx(0.3)
 |          >>> print(x.interp(0))
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |          >>> print(x.interp(1))
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
 |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |          >>> y = x.interp(x, np.linspace(0, 1, 10))
 |          >>> len(y)
 |          10
 |          >>> y[5]
 |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
 |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
 |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
 |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
 |
 |      Notes:
 |
 |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
 |
 |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
 |
 |      :SymPy: not supported
 |
 |  ishom(self) -> 'bool'
 |      Test if object belongs to SE(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          True
 |
 |  ishom2(self) -> 'bool'
 |      Test if object belongs to SE(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SE2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SE2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          False
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          True
 |
 |  isrot(self) -> 'bool'
 |      Test if object belongs to SO(3) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO3
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO3)``.
 |
 |      Example::
 |
 |          >>> x = SO3()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE3()
 |          >>> x.isrot()
 |          False
 |
 |  isrot2(self) -> 'bool'
 |      Test if object belongs to SO(2) group (superclass method)
 |
 |      :return: ``True`` if object is instance of SO2
 |      :rtype: bool
 |
 |      For compatibility with Spatial Math Toolbox for MATLAB.
 |      In Python use ``isinstance(x, SO2)``.
 |
 |      Example::
 |
 |          >>> x = SO2()
 |          >>> x.isrot()
 |          True
 |          >>> x = SE2()
 |          >>> x.isrot()
 |          False
 |
 |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
 |      Logarithm of pose (superclass method)
 |
 |      :return: logarithm
 |      :rtype: ndarray
 |      :raises: ValueError
 |
 |      An efficient closed-form solution of the matrix logarithm.
 |
 |      =====  ======  ===============================
 |      Input         Output
 |      -----  ---------------------------------------
 |      Pose   Shape   Structure
 |      =====  ======  ===============================
 |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
 |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
 |      =====  ======  ===============================
 |
 |      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. ]])
 |
 |
 |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
 |      :func:`~spatialmath.base.transforms3d.trlog`
 |
 |      :SymPy: not supported
 |
 |  norm(self) -> 'Self'
 |      Normalize pose (superclass method)
 |
 |      :return: pose
 |      :rtype: SO2, SE2, SO3, SE3 instance
 |
 |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
 |        part of all values has been adjusted to ensure it is a proper orthogonal
 |        matrix rotation.
 |
 |      Example::
 |
 |          >>> x = SE3()
 |          >>> y = x.norm()
 |          >>> y
 |          SE3(array([[1., 0., 0., 0.],
 |                     [0., 1., 0., 0.],
 |                     [0., 0., 1., 0.],
 |                     [0., 0., 0., 1.]]))
 |
 |      Notes:
 |
 |      #. Only the direction of A vector (the z-axis) is unchanged.
 |      #. Used to prevent finite word length arithmetic causing transforms to
 |         become 'unnormalized'.
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
 |
 |  plot(self, *args, **kwargs) -> 'None'
 |      Plot pose object as a coordinate frame (superclass method)
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
 |        2D or 3D.  There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = SE3.Rx(0.3)
 |          >>> X.plot(frame='A', color='green')
 |
 |      .. plot::
 |
 |          from spatialmath import SE3
 |          X = SE3.Rx(0.3)
 |          X.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
 |
 |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
 |      Print pose as a matrix (superclass method)
 |
 |      :param label: label to print before the matrix, defaults to None
 |      :type label: str, optional
 |      :param file: file to write to, defaults to None
 |      :type file: file object, optional
 |
 |      Print the pose as a matrix, with an optional line beforehand.  By default
 |      the matrix is printed to stdout.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> SE3().print()
 |          >>> SE3().print("pose is:")
 |
 |      :seealso: :meth:`printline` :meth:`strline`
 |
 |  printline(self, *args, **kwargs) -> 'None'
 |      Print pose in compact single line format (superclass method)
 |
 |      :param arg: value for orient option, optional
 |      :type arg: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param file: file to write formatted string to. [default, stdout]
 |      :type file: file object
 |
 |      Print pose in a compact single line format. If ``X`` has multiple
 |      values, print one per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.printline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.printline()
 |          >>> x.printline('angvec')
 |          >>> x.printline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.printline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
 |
 |  prod(self, norm=False, check=True) -> 'Self'
 |      Product of elements (superclass method)
 |
 |      :param norm: normalize the product, defaults to False
 |      :type norm: bool, optional
 |      :param check: check that computed matrix is valid member of group, default True
 |      :bool check: bool, optional
 |      :return: Product of elements
 |      :rtype: pose instance
 |
 |      ``x.prod()`` is the product of the values held by ``x``, ie.
 |      :math:`\prod_i^N T_i`.
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3
 |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
 |          >>> x.prod()
 |
 |      .. note:: When compounding many transformations the product may become
 |          denormalized resulting in a result that is not a proper member of the
 |          group.  You can either disable membership checking by ``check=False``
 |          which is risky, or normalize the result by ``norm=True``.
 |
 |  simplify(self) -> 'Self'
 |      Symbolically simplify matrix values (superclass method)
 |
 |      :return: pose with symbolic elements
 |      :rtype: pose instance
 |
 |      Apply symbolic simplification to every element of every value in the
 |      pose instance.
 |
 |      Example::
 |
 |          >>> a = SE3.Rx(sympy.symbols('theta'))
 |          >>> b = a * a
 |          >>> b
 |          SE3(array([[1, 0, 0, 0.0],
 |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
 |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
 |          [0.0, 0, 0, 1.0]], dtype=object)
 |          >>> b.simplify()
 |          SE3(array([[1, 0, 0, 0],
 |          [0, cos(2*theta), -sin(2*theta), 0],
 |          [0, sin(2*theta), cos(2*theta), 0],
 |          [0, 0, 0, 1.00000000000000]], dtype=object))
 |
 |      .. todo:: No need to simplify the constants in bottom row
 |
 |      :SymPy: supported
 |
 |  stack(self) -> 'NDArray'
 |      Convert to 3-dimensional matrix
 |
 |      :return: 3-dimensional NumPy array
 |      :rtype: ndarray(n,n,m)
 |
 |      Converts the value to a 3-dimensional NumPy array where the values are
 |      stacked along the third axis.  The first two dimensions are given by
 |      ``self.shape``.
 |
 |  strline(self, *args, **kwargs) -> 'str'
 |      Convert pose to compact single line string (superclass method)
 |
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param fmt: conversion format for each number as used by ``format()``
 |      :type fmt: str
 |      :param label: text label to put at start of line
 |      :type label: str
 |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
 |                     only
 |      :type orient: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: pose in string format
 |      :rtype: str
 |
 |      Convert pose in a compact single line format. If ``X`` has multiple
 |      values, the string has one pose per line.
 |
 |      Orientation can be displayed in various formats:
 |
 |      =============   =================================================
 |      ``orient``      description
 |      =============   =================================================
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
 |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
 |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
 |      ``'eul'``       Euler angles in ZYZ axis order
 |      ``'angvec'``    angle and axis
 |      =============   =================================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, SE3
 |          >>> x = SE3.Rx(0.3)
 |          >>> x.strline()
 |          >>> x = SE3.Rx([0.2, 0.3])
 |          >>> x.strline()
 |          >>> x.strline('angvec')
 |          >>> x.strline(orient='angvec', fmt="{:.6f}")
 |          >>> x = SE2(1, 2, 0.3)
 |          >>> x.strline()
 |
 |      .. note::
 |          - Default formatting is for compact display of data
 |          - For tabular data set ``fmt`` to a fixed width format such as
 |            ``fmt='{:.3g}'``
 |
 |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
 |
 |  ----------------------------------------------------------------------
 |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __new__(cls, *args, **kwargs)
 |      Create the subclass instance (superclass method)
 |
 |      Create a new instance and call the superclass initializer to enable the
 |      ``UserList`` capabilities.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  N
 |      Dimension of the object's group (superclass property)
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
 |      This corresponds to the dimension of the space, 2D or 3D, to which these
 |      rotations or rigid-body motions apply.
 |
 |      Example::
 |
 |          >>> SE3().N
 |          3
 |          >>> SE2().N
 |          2
 |
 |  about
 |      Succinct summary of object type and length (superclass property)
 |
 |      :return: succinct summary
 |      :rtype: str
 |
 |      Displays the type and the number of elements in compact form, for
 |      example::
 |
 |          >>> x = SE3([SE3() for i in range(20)])
 |          >>> len(x)
 |          20
 |          >>> print(x.about)
 |          SE3[20]
 |
 |  isSE
 |      Test if object belongs to SE(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SE2 or SE3
 |      :rtype: bool
 |
 |  isSO
 |      Test if object belongs to SO(n) group (superclass property)
 |
 |      :param self: object to test
 |      :type self: SO2, SE2, SO3, SE3 instance
 |      :return: ``True`` if object is instance of SO2 or SO3
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
 |
 |  __array_ufunc__ = None
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __len__(self)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SpatialAcceleration
Python Library Documentation: class SpatialAcceleration in module spatialmath.spatialvector

class SpatialAcceleration(SpatialM6)
 |  SpatialAcceleration(value=None)
 |
 |  Spatial acceleration class
 |
 |  Concrete subclass of SpatialM6 that represents the
 |  translational and rotational acceleration of a rigid-body moving in 3D space.
 |
 |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialAcceleration
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialVelocity`
 |
 |  Method resolution order:
 |      SpatialAcceleration
 |      SpatialM6
 |      SpatialVector
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __init__(self, value=None)
 |      Create a new spatial vector (abstract superclass)
 |
 |      :param value: Value of the
 |
 |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
 |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
 |        array-like values ``Vi``
 |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
 |        array ``A``.
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialM6:
 |
 |  cross(self, other)
 |      Spatial vector cross product
 |
 |      :param other: spatial motion vector
 |      :type other: SpatialM6 instance
 |      :return: cross product of spatial vectors
 |      :rtype: SpatialF6 instance if ``other`` is SpatialF6 instance
 |      :rtype: SpatialM6 instance if ``other`` is SpatialM6 instance
 |
 |      ``v1.cross(v2)`` is a spatial vector cross product whose result depends
 |      on the SpatialVector subclass of ``v2``:
 |
 |      - if :math:`\vec{m} \in \mat{M}^6` is a spatial motion vector fixed in a
 |        body with velocity :math:`\vec{v}` then
 |        :math:`\dvec{m} = \vec{v} \times \vec{m}` or the ``crm()`` function.
 |
 |      - if :math:`\vec{f} \in \mat{F}^6` is a spatial force vector fixed in a
 |        body with velocity :math:`\vec{v}` then
 |        :math:`\dvec{f} = \vec{v} \times^* \vec{f}` or the ``crm()`` function.
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialVector:
 |
 |  __add__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: sum of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to add SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
 |
 |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
 |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
 |      V2 (1xN) the result is an array (1xN).
 |
 |      :seealso: :func:`__sub__`
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __neg__(self)
 |      Overloaded unary ``-`` operator (superclass method)
 |
 |      :return: negative of spatial vector
 |      :rtype: SpatialVector subclass instance
 |
 |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
 |      the element-wise negative of ``v``.
 |
 |      :seealso: :func:`__sub__`
 |
 |  __repr__(self)
 |      :return:
 |      SpatialVec6.display Display parameters
 |
 |      V.display() displays the spatial vector parameters in compact single line format.
 |      If V is an array of spatial vector objects it displays one per line.
 |
 |      Notes:
 |
 |       - This method is invoked implicitly at the command line when the result
 |         of an expression is a serial vector subclass object and the command has
 |         no trailing semicolon.
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: transformed spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: for incompatible left operand
 |
 |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
 |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
 |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
 |      of ``X`` depending on the SpatialVector subclass of ``S``.
 |
 |      ===========  ====================  ===================  =========================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |      left         right                type                 operation
 |      ===========  ====================  ===================  =========================
 |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
 |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
 |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
 |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
 |      ===========  ====================  ===================  =========================
 |
 |  __str__(self)
 |      Pretty string representation (superclass method)
 |
 |      :return: readable representation of the spatial vector
 |      :rtype: str
 |
 |      - ``s = str(v)`` is a string showing spatial vector parameters in a
 |      compact single line format.
 |
 |      If V is an array of spatial vector objects return a string with one
 |      line per element.
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: difference of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
 |
 |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
 |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
 |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
 |      an array (1xN).
 |
 |      :seealso: :func:`__add__`, :func:`__neg__`
 |
 |  isvalid(self, x, check)
 |      Test if vector is valid spatial vector
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: ignored
 |      :type check: bool
 |      :return: True if the matrix has shape (6,).
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SpatialVector:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (6,)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __eq__(self, other)
 |      Return self==value.
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __mul__(self, n)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from collections.UserList:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SpatialForce
Python Library Documentation: class SpatialForce in module spatialmath.spatialvector

class SpatialForce(SpatialF6)
 |  SpatialForce(value=None)
 |
 |  Spatial force class
 |
 |  Concrete subclass of SpatialF6 and represents the
 |  translational and rotational forces and torques acting on a rigid-body in 3D space.
 |
 |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialForce
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  :seealso: :func:`~spatialmath.spatialvector.SpatialF6`, :func:`~spatialmath.spatialvector.SpatialMomentum`
 |
 |  Method resolution order:
 |      SpatialForce
 |      SpatialF6
 |      SpatialVector
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __init__(self, value=None)
 |      Create a new spatial vector (abstract superclass)
 |
 |      :param value: Value of the
 |
 |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
 |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
 |        array-like values ``Vi``
 |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
 |        array ``A``.
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: transformed spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: for incompatible left operand
 |
 |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
 |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
 |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
 |      of ``X`` depending on the SpatialVector subclass of ``S``.
 |
 |      ===========  ====================  ===================  =========================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |      left         right                type                 operation
 |      ===========  ====================  ===================  =========================
 |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
 |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
 |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
 |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
 |      ===========  ====================  ===================  =========================
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialF6:
 |
 |  dot(self, value)
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialVector:
 |
 |  __add__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: sum of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to add SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
 |
 |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
 |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
 |      V2 (1xN) the result is an array (1xN).
 |
 |      :seealso: :func:`__sub__`
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __neg__(self)
 |      Overloaded unary ``-`` operator (superclass method)
 |
 |      :return: negative of spatial vector
 |      :rtype: SpatialVector subclass instance
 |
 |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
 |      the element-wise negative of ``v``.
 |
 |      :seealso: :func:`__sub__`
 |
 |  __repr__(self)
 |      :return:
 |      SpatialVec6.display Display parameters
 |
 |      V.display() displays the spatial vector parameters in compact single line format.
 |      If V is an array of spatial vector objects it displays one per line.
 |
 |      Notes:
 |
 |       - This method is invoked implicitly at the command line when the result
 |         of an expression is a serial vector subclass object and the command has
 |         no trailing semicolon.
 |
 |  __str__(self)
 |      Pretty string representation (superclass method)
 |
 |      :return: readable representation of the spatial vector
 |      :rtype: str
 |
 |      - ``s = str(v)`` is a string showing spatial vector parameters in a
 |      compact single line format.
 |
 |      If V is an array of spatial vector objects return a string with one
 |      line per element.
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: difference of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
 |
 |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
 |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
 |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
 |      an array (1xN).
 |
 |      :seealso: :func:`__add__`, :func:`__neg__`
 |
 |  isvalid(self, x, check)
 |      Test if vector is valid spatial vector
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: ignored
 |      :type check: bool
 |      :return: True if the matrix has shape (6,).
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SpatialVector:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (6,)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __eq__(self, other)
 |      Return self==value.
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __mul__(self, n)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from collections.UserList:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SpatialInertia
Python Library Documentation: class SpatialInertia in module spatialmath.spatialvector

class SpatialInertia(spatialmath.baseposelist.BasePoseList)
 |  SpatialInertia(m=None, r=None, I=None)
 |
 |  Spatial inertia class
 |
 |  Spatial inertia of a body in 3D space.
 |
 |  ========   ===========================================================
 |  Operator   Operation
 |  ========   ===========================================================
 |  ``+``      addition of spatial inertias of joined bodies
 |  ``*``      acceleration x inertia is force
 |  ========   ===========================================================
 |
 |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialF6`, :func:`~spatialmath.spatialvector.SpatialVelocity`, :func:`~spatialmath.spatialvector.SpatialAcceleration`, :func:`~spatialmath.spatialvector.SpatialForce`, :func:`~spatialmath.spatialvector.SpatialMomentum`.
 |
 |  Method resolution order:
 |      SpatialInertia
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __add__(left, right)
 |      Spatial inertia addition
 |      :param left:
 |      :param right:
 |      :return:
 |      :raises TypeError: attempting to add invalid type to SpatialInertia
 |
 |      - ``SI1 + SI2`` is the SpatialInertia of a composite body when bodies with
 |         SpatialInertia ``SI1`` and ``SI2`` are connected.
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __init__(self, m=None, r=None, I=None)
 |      Create a new spatial inertia
 |
 |      :param m: mass
 |      :type m: float
 |      :param r: centre of mass relative to link frame
 |      :type r: 3-element array_like
 |      :param I: inertia about the centre of mass, axes aligned with link frame
 |      :type I: numpy.array, shape=(6,6)
 |
 |      - ``SpatialInertia(m, r, I)`` is a spatial inertia object for a rigid-body
 |        with mass ``m``, centre of mass at ``r`` relative to the link frame, and an
 |        inertia matrix ``I`` (3x3) about the centre of mass.
 |
 |      - ``SpatialInertia(I)`` is a spatial inertia object with a value equal
 |        to ``I`` (6x6).
 |
 |      :SymPy: supported
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :param other: spatial acceleration vector
 |      :type other: SpatialAcceleration instance
 |      :return: force
 |      :rtype: SpatialForce instance if ``other`` is SpatialAcceleration instance
 |      :rtype: SpatialMomentum instance if ``other`` is SpatialVelocity instance
 |
 |      - ``I * a`` is the SpatialForce required for a body with SpatialInertia ``I`` to accelerate with
 |        the SpatialAcceleration ``a``.
 |      - ``I * v`` is the SpatialMomemtum of a body with SpatialInertia ``I`` and SpatialVelocity ``v``.
 |
 |  __repr__(self)
 |      Convert to string
 |
 |      s = SI.char() is a string showing spatial inertia parameters in a
 |      compact format.
 |      If SI is an array of spatial inertia objects return a string with the
 |      inertia values in a vertical list.
 |
 |      See also SpatialInertia.display.
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :param other: spatial acceleration vector
 |      :type other: SpatialAcceleration instance
 |      :return: force
 |      :rtype: SpatialForce instance if ``other`` is SpatialAcceleration instance
 |      :rtype: SpatialMomentum instance if ``other`` is SpatialVelocity instance
 |
 |      - ``a * I`` is the SpatialForce required for a body with SpatialInertia ``I`` to accelerate with
 |        the SpatialAcceleration ``a``.
 |      - ``v * I`` is the SpatialMomemtum of a body with SpatialInertia ``I`` and SpatialVelocity ``v``.
 |
 |  __str__(self)
 |      Return str(self).
 |
 |  isvalid(self, x, check)
 |      Test if matrix is valid spatial inertia
 |
 |      :param x: matrix to test
 |      :type x: numpy.ndarray
 |      :arg check: ignored
 |      :type check: bool
 |      :return: True if the matrix has shape (6,6).
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (6,6)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __eq__(self, other)
 |      Return self==value.
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from collections.UserList:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SpatialMomentum
Python Library Documentation: class SpatialMomentum in module spatialmath.spatialvector

class SpatialMomentum(SpatialF6)
 |  SpatialMomentum(value=None)
 |
 |  Spatial momentum class
 |
 |  Concrete subclass of SpatialF6 and represents the
 |  translational and rotational momentum of a rigid-body in 3D space.
 |
 |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialMomentum
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  :seealso: :func:`~spatialmath.spatialvector.SpatialF6`,  :func:`~spatialmath.spatialvector.SpatialForce`
 |
 |  Method resolution order:
 |      SpatialMomentum
 |      SpatialF6
 |      SpatialVector
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __init__(self, value=None)
 |      Create a new spatial vector (abstract superclass)
 |
 |      :param value: Value of the
 |
 |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
 |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
 |        array-like values ``Vi``
 |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
 |        array ``A``.
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialF6:
 |
 |  dot(self, value)
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialVector:
 |
 |  __add__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: sum of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to add SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
 |
 |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
 |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
 |      V2 (1xN) the result is an array (1xN).
 |
 |      :seealso: :func:`__sub__`
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __neg__(self)
 |      Overloaded unary ``-`` operator (superclass method)
 |
 |      :return: negative of spatial vector
 |      :rtype: SpatialVector subclass instance
 |
 |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
 |      the element-wise negative of ``v``.
 |
 |      :seealso: :func:`__sub__`
 |
 |  __repr__(self)
 |      :return:
 |      SpatialVec6.display Display parameters
 |
 |      V.display() displays the spatial vector parameters in compact single line format.
 |      If V is an array of spatial vector objects it displays one per line.
 |
 |      Notes:
 |
 |       - This method is invoked implicitly at the command line when the result
 |         of an expression is a serial vector subclass object and the command has
 |         no trailing semicolon.
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: transformed spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: for incompatible left operand
 |
 |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
 |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
 |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
 |      of ``X`` depending on the SpatialVector subclass of ``S``.
 |
 |      ===========  ====================  ===================  =========================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |      left         right                type                 operation
 |      ===========  ====================  ===================  =========================
 |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
 |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
 |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
 |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
 |      ===========  ====================  ===================  =========================
 |
 |  __str__(self)
 |      Pretty string representation (superclass method)
 |
 |      :return: readable representation of the spatial vector
 |      :rtype: str
 |
 |      - ``s = str(v)`` is a string showing spatial vector parameters in a
 |      compact single line format.
 |
 |      If V is an array of spatial vector objects return a string with one
 |      line per element.
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: difference of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
 |
 |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
 |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
 |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
 |      an array (1xN).
 |
 |      :seealso: :func:`__add__`, :func:`__neg__`
 |
 |  isvalid(self, x, check)
 |      Test if vector is valid spatial vector
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: ignored
 |      :type check: bool
 |      :return: True if the matrix has shape (6,).
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SpatialVector:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (6,)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __eq__(self, other)
 |      Return self==value.
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __mul__(self, n)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from collections.UserList:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SpatialVelocity
Python Library Documentation: class SpatialVelocity in module spatialmath.spatialvector

class SpatialVelocity(SpatialM6)
 |  SpatialVelocity(value=None)
 |
 |  Spatial velocity class
 |
 |  Concrete subclass of SpatialM6 that represents the
 |  translational and rotational velocity of a rigid-body moving in 3D space.
 |
 |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialVelocity
 |     :top-classes: collections.UserList
 |     :parts: 1
 |
 |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialAcceleration`
 |
 |  Method resolution order:
 |      SpatialVelocity
 |      SpatialM6
 |      SpatialVector
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  __init__(self, value=None)
 |      Create a new spatial vector (abstract superclass)
 |
 |      :param value: Value of the
 |
 |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
 |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
 |        array-like values ``Vi``
 |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
 |        array ``A``.
 |
 |  __matmul__(self, other)
 |      Overloaded ``@`` operator (superclass method)
 |
 |      :param other: spatial velocity vector
 |      :type other: SpatialVelocity or SpatialMomentum instance
 |      :return: cross product of spatial vectors
 |      :rtype: SpatialAcceleration instance if ``other`` is SpatialVelocity instance
 |      :rtype: SpatialMomentum instance if ``other`` is SpatialForce instance
 |
 |      This operator implements the spatial vector cross product.
 |
 |      - ``v1 @v2`` is spatial acceleration given spatial velocities
 |        ``v1`` and ``v2`` or :math:`\vec{v}_1 \times \vec{v}_2`
 |      - ``v1 @ m2`` is spatial force given spatial velocity
 |        ``v1`` and spatial momentum ``m2`` or :math:`\vec{v}_1 \times^* \vec{m}_2`
 |
 |      .. note:: The ``@`` operator was chosen because it has high precendence
 |          and is somewhat invocative of multiplication.
 |
 |      :seealso: :func:`~spatialmath.spatialvector.SpatialVelocity.cross`
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialM6:
 |
 |  cross(self, other)
 |      Spatial vector cross product
 |
 |      :param other: spatial motion vector
 |      :type other: SpatialM6 instance
 |      :return: cross product of spatial vectors
 |      :rtype: SpatialF6 instance if ``other`` is SpatialF6 instance
 |      :rtype: SpatialM6 instance if ``other`` is SpatialM6 instance
 |
 |      ``v1.cross(v2)`` is a spatial vector cross product whose result depends
 |      on the SpatialVector subclass of ``v2``:
 |
 |      - if :math:`\vec{m} \in \mat{M}^6` is a spatial motion vector fixed in a
 |        body with velocity :math:`\vec{v}` then
 |        :math:`\dvec{m} = \vec{v} \times \vec{m}` or the ``crm()`` function.
 |
 |      - if :math:`\vec{f} \in \mat{F}^6` is a spatial force vector fixed in a
 |        body with velocity :math:`\vec{v}` then
 |        :math:`\dvec{f} = \vec{v} \times^* \vec{f}` or the ``crm()`` function.
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from SpatialVector:
 |
 |  __add__(left, right)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: sum of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to add SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
 |
 |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
 |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
 |      V2 (1xN) the result is an array (1xN).
 |
 |      :seealso: :func:`__sub__`
 |
 |  __getitem__(self, i)
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __neg__(self)
 |      Overloaded unary ``-`` operator (superclass method)
 |
 |      :return: negative of spatial vector
 |      :rtype: SpatialVector subclass instance
 |
 |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
 |      the element-wise negative of ``v``.
 |
 |      :seealso: :func:`__sub__`
 |
 |  __repr__(self)
 |      :return:
 |      SpatialVec6.display Display parameters
 |
 |      V.display() displays the spatial vector parameters in compact single line format.
 |      If V is an array of spatial vector objects it displays one per line.
 |
 |      Notes:
 |
 |       - This method is invoked implicitly at the command line when the result
 |         of an expression is a serial vector subclass object and the command has
 |         no trailing semicolon.
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator (superclass method)
 |
 |      :return: transformed spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: for incompatible left operand
 |
 |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
 |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
 |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
 |      of ``X`` depending on the SpatialVector subclass of ``S``.
 |
 |      ===========  ====================  ===================  =========================
 |                 Multiplicands                   Product
 |      -------------------------------   -----------------------------------
 |      left         right                type                 operation
 |      ===========  ====================  ===================  =========================
 |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
 |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
 |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
 |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
 |      ===========  ====================  ===================  =========================
 |
 |  __str__(self)
 |      Pretty string representation (superclass method)
 |
 |      :return: readable representation of the spatial vector
 |      :rtype: str
 |
 |      - ``s = str(v)`` is a string showing spatial vector parameters in a
 |      compact single line format.
 |
 |      If V is an array of spatial vector objects return a string with one
 |      line per element.
 |
 |  __sub__(left, right)
 |      Overloaded ``-`` operator (superclass method)
 |
 |      :return: difference of spatial vectors
 |      :rtype: SpatialVector subclass instance
 |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
 |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
 |
 |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
 |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
 |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
 |      an array (1xN).
 |
 |      :seealso: :func:`__add__`, :func:`__neg__`
 |
 |  isvalid(self, x, check)
 |      Test if vector is valid spatial vector
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: ignored
 |      :type check: bool
 |      :return: True if the matrix has shape (6,).
 |      :rtype: bool
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from SpatialVector:
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (6,)
 |      :rtype: tuple
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __eq__(self, other)
 |      Return self==value.
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __mul__(self, n)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from collections.UserList:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.SplineFit
Python Library Documentation: class SplineFit in module spatialmath.spline

class SplineFit(builtins.object)
 |  SplineFit(time_data: List[float], pose_data: List[spatialmath.pose3d.SE3]) -> None
 |
 |  A general class to fit various SE3 splines to data.
 |
 |  Methods defined here:
 |
 |  __init__(self, time_data: List[float], pose_data: List[spatialmath.pose3d.SE3]) -> None
 |      Initialize self.  See help(type(self)) for accurate signature.
 |
 |  angular_errors(self) -> List[float]
 |
 |  euclidean_errors(self) -> List[float]
 |
 |  max_angular_error(self) -> float
 |
 |  max_euclidean_error(self) -> float
 |
 |  stochastic_downsample_interpolation(self, epsilon_xyz: float = 0.001, epsilon_angle: float = 0.1, normalize_time: bool = True, bc_type: str = 'not-a-knot', check_type: str = 'local') -> Tuple[spatialmath.spline.InterpSplineSE3, List[int]]
 |      Uses a random dropout to downsample a trajectory with an interpolated spline. Keeps the start and
 |      end points of the trajectory. Takes a random order of the remaining indices, and then checks the error bound
 |      of just that point if check_type=="local", checks the error of the whole trajectory is check_type=="global".
 |      Local is **much** faster.
 |
 |          Return:
 |              downsampled interpolating spline,
 |              list of removed indices from input data
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.Twist2
Python Library Documentation: class Twist2 in module spatialmath.twist

class Twist2(BaseTwist)
 |  Twist2(arg=None, w=None, check=True)
 |
 |  Method resolution order:
 |      Twist2
 |      BaseTwist
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  SE2(self, theta=1, unit='rad')
 |      Convert 2D twist to SE(2) matrix
 |
 |      :return: an SE(2) representation
 |      :rtype: SE3 instance
 |
 |      ``S.SE2()`` is an SE2 object representing the homogeneous transformation
 |      equivalent to the Twist2. This is the exponentiation of the twist vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> S = Twist2.Prismatic([1,2])
 |          >>> S.SE2()
 |
 |      :seealso: :func:`Twist3.exp`
 |
 |  __init__(self, arg=None, w=None, check=True)
 |          Construct a new 2D Twist object
 |
 |          :type a: 2-element array-like
 |          :return: 2D prismatic twist
 |          :rtype: Twist2 instance
 |
 |          - ``Twist2(R)`` is a 2D Twist object representing the SO(2) rotation expressed as
 |            a 2x2 matrix.
 |          - ``Twist2(T)`` is a 2D Twist object representing the SE(2) rigid-body motion expressed as
 |            a 3x3 matrix.
 |          - ``Twist2(X)`` if X is an SO2 instance then create a 2D Twist object representing the SO(2) rotation,
 |            and if X is an SE2 instance then create a 2D Twist object representing the SE(2) motion
 |          - ``Twist2(V)`` is a  2D Twist object specified directly by a 3-element array-like comprising the
 |            moment vector (1 element) and direction vector (2 elements).
 |
 |      :References:
 |          - Robotics, Vision & Control for Python, Section 2.2.2.4, P. Corke, Springer 2023.
 |          - Modern Robotics, Lynch & Park, Cambridge 2017
 |
 |      .. note:: Compared to Lynch & Park this module implements twist vectors
 |          with the translational components first, followed by rotational
 |          components, ie. :math:`[\omega, \vec{v}]`.
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator
 |
 |      :arg left: left multiplicand
 |      :arg right: right multiplicand
 |      :return: product
 |      :raises: ValueError
 |
 |      - ``X * Y`` compounds the twists ``X`` and ``Y``
 |      - ``X * s`` performs elementwise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
 |
 |      ========  ====================  ===================  ========================
 |           Multiplicands                   Product
 |      ------------------------------  ---------------------------------------------
 |         left      right                 type                 operation
 |      ========  ====================  ===================  ========================
 |      Twist2    Twist2                Twist2               product of exponentials
 |      Twist2    scalar                Twist2               element-wise product
 |      scalar    Twist2                Twist2               element-wise product
 |      Twist2    SE2                   Twist2               exponential x SE2
 |      ========  ====================  ===================  ========================
 |
 |      .. note::
 |
 |          #. scalar x Twist is handled by ``__rmul__``
 |          #. scalar multiplication is commutative but the result is not a group
 |          operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition the ``left`` and ``right`` operands may be a sequence
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __repr__(self)
 |      Readable representation of 2D twist
 |
 |      :return: readable representation of a twist as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> x = Twist2([1,2,3])
 |          >>> x
 |          >>> a.append(a)
 |          >>> a
 |
 |  __str__(self)
 |      Pretty string representation of 2D twist
 |
 |      :return: readable representation of the twist
 |      :rtype: str
 |
 |      Convert the twist's value to an array of numbers.
 |
 |      Example:
 |
 |      .. runblock: pycon
 |
 |          >>> x = Twist2([1,2,3])
 |          >>> print(x)
 |
 |  exp(self, theta=1, unit='rad')
 |      Exponentiate a 2D twist
 |
 |      :param theta: rotation magnitude, defaults to None
 |      :type theta: float, optional
 |      :param unit: rotational units, defaults to 'rad'
 |      :type unit: str, optional
 |      :return: SE(2) matrix
 |      :rtype: SE2 instance
 |
 |      - ``X.exp()`` is the homogeneous transformation equivalent to the twist,
 |        :math:`e^{[S]}`
 |      - ``X.exp(θ) as above but with a rotation of ``θ`` about the twist axis,
 |        :math:`e^{\theta[S]}`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE2, Twist2
 |          >>> T = SE2(1, 2, 0.3)
 |          >>> S = Twist2(T)
 |          >>> S.exp(0)
 |          >>> S.exp(1)
 |
 |      .. note::
 |
 |          - For the second form, the twist must, if rotational, have a unit
 |            rotational component.
 |
 |      :seealso: :func:`spatialmath.smb.trexp2`
 |
 |  printline(self, **kwargs)
 |
 |  skewa(self)
 |      Convert 2D twist to se(2)
 |
 |      :return: An se(2) matrix
 |      :rtype: ndarray(3,3)
 |
 |      ``X.skewa()`` is the twist as a 3x3 augmented skew-symmetric matrix
 |      belonging to the group se(2). This is the Lie algebra of the
 |      corresponding SE(2) element.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2, base
 |          >>> S = Twist2([1,2,3])
 |          >>> se = S.skewa()
 |          >>> se
 |          >>> smb.trexp2(se)
 |
 |  unit(self)
 |      Unit twist
 |
 |      - ``S.unit()`` is a Twist2 object representing a unit twist aligned with the
 |        Twist ``S``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE2(1, 2, 0.3)
 |          >>> S = Twist2(T)
 |          >>> S.unit()
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  Tx(x)
 |      Create a new 2D twist for pure translation along the X-axis
 |
 |      :param x: translation distance along the X-axis
 |      :type x: float
 |      :return: 2D twist vector
 |      :rtype: Twist2 instance
 |
 |      `Twist2.Tx(x)` is an se(2) translation of ``x`` along the x-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> Twist2.Tx(2)
 |          >>> Twist2.Tx([2,3])
 |
 |
 |      :seealso: :func:`~spatialmath.smb.transforms2d.transl2`
 |      :SymPy: supported
 |
 |  Ty(y)
 |      Create a new 2D twist for pure translation along the Y-axis
 |
 |      :param y: translation distance along the Y-axis
 |      :type y: float
 |      :return: 2D twist vector
 |      :rtype: Twist2 instance
 |
 |      `Twist2.Ty(y) is an se(2) translation of ``y`` along the y-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> Twist2.Ty(2)
 |          >>> Twist2.Ty([2, 3])
 |
 |
 |      :seealso: :func:`~spatialmath.smb.transforms2d.transl2`
 |      :SymPy: supported
 |
 |  UnitPrismatic(a)
 |      Construct a new 2D primsmatic unit twist
 |
 |      :param a: Displacment
 |      :type a: array-like(2)
 |      :return: 2D prismatic twist
 |      :rtype: Twist2 instance
 |
 |      - ``Twist2.Prismatic(a)`` is a 2D Twist object representing 2D-translation in the direction ``a``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> Twist2.Prismatic([1, 2])
 |
 |  UnitRevolute(q)
 |      Construct a new 2D revolute unit twist
 |
 |      :param q: Point on the line of action
 |      :type q: array_like(2)
 |      :return: 2D prismatic twist
 |      :rtype: Twist2 instance
 |
 |      - ``Twist2.Revolute(q)`` is a 2D Twist object representing rotation about the 2D point ``q``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> Twist2.Revolute([0, 1])
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(v, check=True)
 |      Test if matrix is valid twist
 |
 |      :param x: array to test
 |      :type x: ndarray
 |      :return: Whether the value is a 3-vector or a valid 3x3 se(2) element
 |      :rtype: bool
 |
 |      A twist can be represented by a 6-vector or a 4x4 skew symmetric matrix,
 |      for example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2, base
 |          >>> import numpy as np
 |          >>> Twist2.isvalid([1, 2, 3])
 |          >>> a = smb.skewa([1, 2, 3])
 |          >>> a
 |          >>> Twist2.isvalid(a)
 |          >>> Twist2.isvalid(np.random.rand(3,3))
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  N
 |      Dimension of the object's group
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 2 for ``Twist2`` and corresponds to the
 |      dimension of the space (2D in this case) to which these
 |      rigid-body motions apply.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> x = Twist2()
 |          >>> x.N
 |
 |  ad
 |      Twist2.ad Logarithm of adjoint
 |
 |      - ``S.ad()`` is the logarithm of the adjoint matrix of the corresponding
 |        homogeneous transformation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE2(1, 2, 0.3)
 |          >>> S = Twist2(T)
 |          >>> S.unit()
 |
 |      :seealso: SE3.Ad.
 |
 |  pole
 |      Pole of a 2D twist
 |
 |      :return: the pole of the twist
 |      :rtype: ndarray(2)
 |
 |      ``X.pole()`` is a point on the twist axis. For a pure translation
 |      this point is at infinity.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE2(1, 2, 0.3)
 |          >>> S = Twist2(T)
 |          >>> S.pole()
 |
 |  shape
 |      Shape of the object's interal array representation
 |
 |      :return: (3,)
 |      :rtype: tuple
 |
 |  v
 |      Moment vector of twist
 |
 |      :return: Moment vector
 |      :rtype: ndarray(2)
 |
 |      ``X.v`` is a 2-vector representing the moment vector of the twist.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> t = Twist2([1, 2, 3])
 |          >>> t.v
 |
 |  w
 |      Direction vector of twist
 |
 |      :return: Direction vector
 |      :rtype: float
 |
 |      ``X.w`` is a scalar representing the direction "vector" of the twist.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> t = Twist2([1, 2, 3])
 |          >>> t.w
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from BaseTwist:
 |
 |  __eq__(left, right)
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      ``S1 == S2`` is True if ``S1` is elementwise equal to ``S2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> S1 = Twist3([1,2,3,4,5,6])
 |          >>> S2 = Twist3([1,2,3,4,5,6])
 |          >>> S1 == S2
 |          >>> S2 = Twist3([1,2,3,4,5,7])
 |          >>> S1 == S2
 |
 |      :seealso: :func:`__ne__`
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :rtype: bool
 |
 |      ``S1 == S2`` is True if ``S1` is not elementwise equal to ``S2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S1 = Twist3([1,2,3,4,5,6])
 |          >>> S2 = Twist3([1,2,3,4,5,6])
 |          >>> S1 != S2
 |          >>> S2 = Twist3([1,2,3,4,5,7])
 |          >>> S1 != S2
 |
 |      :seealso: :func:`__ne__`
 |
 |  __truediv__(left, right)
 |
 |  inv(self)
 |      Inverse of Twist (superclass method)
 |
 |      :return: inverse
 |      :rtype: Twist instance
 |
 |      Compute the inverse of each of the values within the twist instance.
 |      The inverse is the negative of the twist vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3(SE3.Rand())
 |          >>> S
 |          >>> S.inv()
 |          >>> S * S.inv()
 |
 |  prod(self)
 |      Product of twists (superclass method)
 |
 |      :return: Product of elements
 |      :rtype: Twist2 or Twist3
 |
 |      For a twist instance with N values return the matrix product of those
 |      elements :math:`\prod_i=0^{N-1} S_i`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3.Rx([0.2, 0.3, 0.4])
 |          >>> len(S)
 |          >>> S.prod()
 |          >>> Twist3.Rx(0.9)
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from BaseTwist:
 |
 |  S
 |      Twist as a vector (superclass property)
 |
 |      :return: Twist vector
 |      :rtype: ndarray(N)
 |
 |      - ``X.S`` is a 3-vector if X is a ``Twist2`` instance, and a 6-vector if
 |        X is a ``Twist3`` instance.
 |
 |      .. note::
 |
 |          - the vector is the unique elements of the se(N) representation.
 |          - the vector is sometimes referred to as the twist coordinate vector.
 |          - if ``len(X)`` > 1 then return a list of vectors.
 |
 |  isprismatic
 |      Test for prismatic twist (superclass property)
 |
 |      :return: Whether twist is purely prismatic
 |      :rtype: bool
 |
 |      A prismatic twist has :math:`\vec{\omega} = 0`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.UnitPrismatic([1,2,3])
 |          >>> x.isprismatic
 |          >>> x = Twist3.UnitRevolute([1,2,3], [4,5,6])
 |          >>> x.isprismatic
 |
 |  isrevolute
 |      Test for revolute twist (superclass property)
 |
 |      :return: Whether twist is purely revolute
 |      :rtype: bool
 |
 |      A revolute twist has :math:`\vec{v} = 0`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.UnitPrismatic([1,2,3])
 |          >>> x.isrevolute
 |          >>> x = Twist3.UnitRevolute([1,2,3], [0,0,0])
 |          >>> x.isrevolute
 |
 |  isunit
 |      Test for unit twist (superclass property)
 |
 |      :return: Whether twist is a unit-twist
 |      :rtype: bool
 |
 |      A unit twist is one with a norm of 1, ie. :math:`\| S \| = 1`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3([1,2,3,4,5,6])
 |          >>> S.isunit()
 |          >>> S = Twist3.UnitRevolute([1,2,3], [4,5,6])
 |          >>> S.isunit()
 |
 |  theta
 |      Twist angle (superclass method)
 |
 |      :return: magnitude of rotation (1x1) about the twist axis in radians
 |      :rtype: float
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from BaseTwist:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __add__(self, other)
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  __rmul__ = __mul__(self, n)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.Twist3
Python Library Documentation: class Twist3 in module spatialmath.twist

class Twist3(BaseTwist)
 |  Twist3(arg=None, w=None, check=True)
 |
 |  3D twist class
 |
 |  A Twist class holds the parameters of a twist, a representation of a
 |  3D rigid body transformation which is the unique elements of the Lie
 |  algebra se(3) of the corresponding SE(3) matrix.
 |
 |  :References:
 |      - Robotics, Vision & Control for Python, Section 2.3.2.3, P. Corke, Springer 2023.
 |      - Modern Robotics, Lynch & Park, Cambridge 2017
 |
 |  .. note:: Compared to Lynch & Park this module implements twist vectors
 |      with the translational components first, followed by rotational
 |      components, ie. :math:`[\omega, \vec{v}]`.
 |
 |  Method resolution order:
 |      Twist3
 |      BaseTwist
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  Ad(self)
 |      Adjoint of 3D twist
 |
 |      :return: adjoint matrix
 |      :rtype: ndarray(6,6)
 |
 |      ``S.Ad()`` is the 6x6 adjoint matrix of the corresponding
 |      homogeneous transformation.
 |
 |      For a twist representing motion from frame {B} to {A}, the adjoint will
 |      transform a twist relative to frame {A} to one relative to frame {B}.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3.Rx(0.3)
 |          >>> S.Ad()
 |
 |      .. note:: This method computes the equivalent SE(3) matrix, then the adjoint
 |          of that.
 |
 |      :seealso: :func:`Twist3.ad`, :func:`Twist3.SE3`, :func:`Twist3.exp`
 |
 |  SE3(self, theta=1, unit='rad')
 |      Convert 3D twist to SE(3) matrix
 |
 |      :return: an SE(3) representation
 |      :rtype: SE3 instance
 |
 |      ``S.SE3()`` is an SE3 object representing the homogeneous transformation
 |      equivalent to the Twist3. This is the exponentiation of the twist vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3.Rx(0.3)
 |          >>> S.SE3()
 |
 |      :seealso: :func:`Twist3.exp`
 |
 |  __init__(self, arg=None, w=None, check=True)
 |      Construct a new 3D twist object
 |
 |      - ``Twist3()`` is a Twist3 instance representing null motion -- the
 |        identity twist
 |      - ``Twist3(S)`` is a Twist3 instance from an array-like (6,)
 |      - ``Twist3(v, w)`` is a Twist3 instance from a moment ``v`` (3,) and
 |        direction ``w`` (3,)
 |      - ``Twist3([S1, S2, ... SN])`` where each ``Si`` is a numpy array (6,)
 |      - ``Twist3(X)`` is a Twist3 instance with the same value as ``X``, ie.
 |        a copy
 |      - ``Twist3([X1, X2, ... XN])`` where each Xi is a Twist3 instance, is a
 |        Twist3 instance containing N motions
 |
 |  __mul__(left, right)
 |      Overloaded ``*`` operator
 |
 |      :arg left: left multiplicand
 |      :arg right: right multiplicand
 |      :return: product
 |      :raises: ValueError
 |
 |      Twist composition or scaling:
 |
 |      - ``X * Y`` compounds the twists ``X`` and ``Y``
 |      - ``X * s`` performs elementwise multiplication of the elements of ``X`` by ``s``
 |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
 |
 |      ========  ====================  ===================  ========================
 |           Multiplicands                   Product
 |      ------------------------------  ---------------------------------------------
 |         left      right                 type                 operation
 |      ========  ====================  ===================  ========================
 |      Twist3    Twist3                Twist3               product of exponentials
 |      Twist3    scalar                Twist3               element-wise product
 |      scalar    Twist3                Twist3               element-wise product
 |      Twist3    SE3                   Twist3               exponential x SE3
 |      ========  ====================  ===================  ========================
 |
 |      .. note::
 |
 |          #. scalar x Twist is handled by ``__rmul__``
 |          #. scalar multiplication is commutative but the result is not a group
 |          operation so the result will be a matrix
 |          #. Any other input combinations result in a ValueError.
 |
 |      For pose composition the ``left`` and ``right`` operands may be a sequence
 |
 |      =========   ==========   ====  ================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ================================
 |       1          1             1    ``prod = left * right``
 |       1          M             M    ``prod[i] = left * right[i]``
 |       N          1             M    ``prod[i] = left[i] * right``
 |       M          M             M    ``prod[i] = left[i] * right[i]``
 |      =========   ==========   ====  ================================
 |
 |  __repr__(self)
 |      Readable representation of 3D twist
 |
 |      :return: readable representation of a twist as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.R([1,2,3], [4,5,6])
 |          >>> x
 |          >>> a.append(a)
 |          >>> a
 |
 |  __rmul__(right, left)
 |      Overloaded ``*`` operator
 |
 |      :arg right: right multiplicand
 |      :arg left: left multiplicand
 |      :return: product
 |      :raises: NotImplemented
 |
 |      Left-multiplication by a scalar
 |
 |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
 |
 |  __str__(self)
 |      Pretty string representation of 3D twist
 |
 |      :return: readable representation of the twist
 |      :rtype: str
 |
 |      Convert the twist's value to an array of numbers.
 |
 |      Example:
 |
 |      .. runblock: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.R([1,2,3], [4,5,6])
 |          >>> print(x)
 |
 |  ad(self)
 |      Logarithm of adjoint of 3D twist
 |
 |      :return: logarithm of adjoint matrix
 |      :rtype: ndarray(6,6)
 |
 |      ``S.ad()`` is the 6x6 logarithm of the adjoint matrix of the
 |      corresponding homogeneous transformation.
 |
 |      For a twist representing motion from frame {B} to {A}, the adjoint will
 |      transform a twist relative to frame {A} to one relative to frame {B}.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3.Rx(0.3)
 |          >>> S.ad()
 |
 |      .. note:: An alternative approach to computing the adjoint is to exponentiate this 6x6
 |          matrix.
 |
 |      :seealso: :func:`Twist3.Ad`
 |
 |  exp(self, theta=1, unit='rad')
 |      Exponentiate a 3D twist
 |
 |      :param theta: rotation magnitude, defaults to None
 |      :type theta: float, optional
 |      :param units: rotational units, defaults to 'rad'
 |      :type units: str, optional
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      - ``X.exp()`` is the homogeneous transformation equivalent to the twist,
 |        :math:`e^{[S]}`
 |      - ``X.exp(θ) as above but with a rotation of ``θ`` about the twist axis,
 |        :math:`e^{    heta[S]}`
 |
 |      If ``len(X)==1`` and ``len(θ)==N`` then the resulting SE3 object has
 |      ``N`` values equivalent to the twist :math:`e^{ heta_i[S]}`.
 |
 |      If ``len(X)==N`` and ``len(θ)==1`` then the resulting SE3 object has
 |      ``N`` values equivalent to the twist :math:`e^{ heta[S_i]}`.
 |
 |      If ``len(X)==N`` and ``len(θ)==N`` then the resulting SE3 object has
 |      ``N`` values equivalent to the twist :math:`e^{ heta_i[S_i]}`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
 |          >>> S = Twist3(T)
 |          >>> S.exp(0)
 |          >>> S.exp(1)
 |
 |      .. note::
 |
 |          - For the second form, the twist must, if rotational, have a unit
 |            rotational component.
 |
 |      :seealso: :func:`spatialmath.smb.trexp`
 |
 |  line(self)
 |      Line of action of 3D twist as a Plucker line
 |
 |      :return: the 3D line of action
 |      :rtype: Line instance
 |
 |      ``X.line()`` is a Plucker object representing the line of the twist axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
 |          >>> S = Twist3(T)
 |          >>> S.line()
 |
 |  printline(self, **kwargs)
 |
 |  skewa(self)
 |      Convert 3D twist to se(3)
 |
 |      :return: An se(3) matrix
 |      :rtype: ndarray(4,4)
 |
 |      ``X.skewa()`` is the twist as a 4x4 augmented skew-symmetric matrix
 |      belonging to the group se(3). This is the Lie algebra of the
 |      corresponding SE(3) element.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3, base
 |          >>> S = Twist3.Rx(0.3)
 |          >>> se = S.skewa()
 |          >>> se
 |          >>> smb.trexp(se)
 |
 |  unit(self)
 |      Unit twist
 |
 |      - ``S.unit()`` is a Twist2 objec3 representing a unit twist aligned with the
 |        Twist ``S``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE3(1, 2, 0.3)
 |          >>> S = Twist3(T)
 |          >>> S.unit()
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  RPY(*pos, **kwargs)
 |      Create a new 3D twist from roll-pitch-yaw angles
 |
 |      :param 𝚪: roll-pitch-yaw angles
 |      :type 𝚪: array_like or numpy.ndarray with shape=(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
 |      :type order: str
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      - ``Twist3.RPY(𝚪)`` is a 3D rotation defined by a 3-vector of roll,
 |        pitch, yaw angles :math:`\Gamma=(r, p, y)` which correspond to
 |        successive rotations about the axes specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  This is the **convention** for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. This is the **convention** for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. This is the **convention** for a camera with z-axis parallel
 |            to the optical axis and x-axis parallel to the pixel rows.
 |
 |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of rotations each defined by RPY angles
 |      corresponding to the rows of ``𝚪``.
 |
 |      - ``Twist3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
 |        scalars.
 |
 |      Foo bar!
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.RPY(0.1, 0.2, 0.3)
 |          >>> Twist3.RPY([0.1, 0.2, 0.3])
 |          >>> Twist3.RPY(0.1, 0.2, 0.3, order='xyz')
 |          >>> Twist3.RPY(10, 20, 30, unit='deg')
 |
 |      :seealso: :meth:`~spatialmath.SE3.RPY`
 |      :SymPy: supported
 |
 |  Rand(*, xrange=(-1, 1), yrange=(-1, 1), zrange=(-1, 1), N=1)
 |      Create a new random 3D twist
 |
 |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
 |      :type xrange: 2-element sequence, optional
 |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
 |      :type yrange: 2-element sequence, optional
 |      :param zrange: z-axis range [min,max], defaults to [-1, 1]
 |      :type zrange: 2-element sequence, optional
 |      :param N: number of random transforms
 |      :type N: int
 |      :return: SE(3) matrix
 |      :rtype: SE3 instance
 |
 |      Return an SE3 instance with random rotation and translation.
 |
 |      - ``SE3.Rand()`` is a random SE(3) translation.
 |      - ``SE3.Rand(N=N)`` is an SE3 object containing a sequence of N random
 |        poses.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Rand(N=2)
 |
 |      :seealso: :func:`~spatialmath.quaternions.UnitQuaternion.Rand`
 |
 |  Rx(theta, unit='rad')
 |      Create a new 3D twist for pure rotation about the X-axis
 |
 |      :param θ: rotation angle about X-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      - ``Twist3.Rx(θ)`` is an SE(3) rotation of θ radians about the x-axis
 |      - ``Twist3.Rx(θ, "deg")`` as above but θ is in degrees
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Rx(0.3)
 |          >>> Twist3.Rx([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.trotx`
 |      :SymPy: supported
 |
 |  Ry(theta, unit='rad', t=None)
 |      Create a new 3D twist for pure rotation about the Y-axis
 |
 |      :param θ: rotation angle about X-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      - ``Twist3.Ry(θ)`` is an SO(3) rotation of θ radians about the y-axis
 |      - ``Twist3.Ry(θ, "deg")`` as above but θ is in degrees
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Ry(0.3)
 |          >>> Twist3.Ry([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.troty`
 |      :SymPy: supported
 |
 |  Rz(theta, unit='rad', t=None)
 |      Create a new 3D twist for pure rotation about the Z-axis
 |
 |      :param θ: rotation angle about Z-axis
 |      :type θ: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      - ``Twist3.Rz(θ)`` is an SO(3) rotation of θ radians about the z-axis
 |      - ``Twist3.Rz(θ, "deg")`` as above but θ is in degrees
 |
 |      If ``θ`` is an array then the result is a sequence of rotations defined
 |      by consecutive elements.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Rz(0.3)
 |          >>> Twist3.Rz([0.3, 0.4])
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.trotz`
 |      :SymPy: supported
 |
 |  Tx(x)
 |      Create a new 3D twist for pure translation along the X-axis
 |
 |      :param x: translation distance along the X-axis
 |      :type x: float
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      ``Twist3.Tx(x)`` is an se(3) translation of ``x`` along the x-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Tx(2)
 |          >>> Twist3.Tx([2,3])
 |
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Ty(y)
 |      Create a new 3D twist for pure translation along the Y-axis
 |
 |      :param y: translation distance along the Y-axis
 |      :type y: float
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      ``Twist3.Ty(y)`` is an se(3) translation of ``y`` along the y-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Ty(2)
 |          >>> Twist3.Ty([2, 3])
 |
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
 |      :SymPy: supported
 |
 |  Tz(z)
 |      Create a new 3D twist for pure translation along the Z-axis
 |
 |      :param z: translation distance along the Z-axis
 |      :type z: float
 |      :return: 3D twist vector
 |      :rtype: Twist3 instance
 |
 |      ``Twist3.Tz(z)`` is an se(3) translation of ``z`` along the z-axis
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Tz(2)
 |          >>> Twist3.Tz([2, 3])
 |
 |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
 |      :SymPy: supported
 |
 |  UnitPrismatic(a)
 |      Construct a new 3D unit prismatic twist
 |
 |      :param a: Twist axis or line of action
 |      :type a: array_like(3)
 |      :return: a prismatic twist
 |      :rtype: Twist instance
 |
 |      A prismatic twist with a line of action in the z-direction would be:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Prismatic([0, 0, 1])
 |
 |  UnitRevolute(a, q, pitch=None)
 |      Construct a new 3D rotational unit twist
 |
 |      :param a: Twist axis or line of action
 |      :type a: array_like(3)
 |      :param q: Point on the line of action
 |      :type q: array_like(3)
 |      :param p: pitch, defaults to None
 |      :type p: float, optional
 |      :return: a rotational or helical twist
 |      :rtype: Twist instance
 |
 |      A revolute twist with a line of action in the z-direction and passing
 |      through (1, 2, 0) would be:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> Twist3.Revolute([0, 0, 1], [1, 2, 0])
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(v, check=True)
 |      Test if matrix is valid twist
 |
 |      :param x: array to test
 |      :type x: ndarray
 |      :return: Whether the value is a 6-vector or a valid 4x4 se(3) element
 |      :rtype: bool
 |
 |      A twist can be represented by a 6-vector or a 4x4 skew symmetric matrix,
 |      for example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> from spatialmath.base import skewa
 |          >>> import numpy as np
 |          >>> Twist3.isvalid([1, 2, 3, 4, 5, 6])
 |          >>> a = skewa([1, 2, 3, 4, 5, 6])
 |          >>> a
 |          >>> Twist3.isvalid(a)
 |          >>> Twist3.isvalid(np.random.rand(4,4))
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  N
 |      Dimension of the object's group
 |
 |      :return: dimension
 |      :rtype: int
 |
 |      Dimension of the group is 3 for ``Twist3`` and corresponds to the
 |      dimension of the space (3D in this case) to which these
 |      rigid-body motions apply.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3()
 |          >>> x.N
 |
 |  pitch
 |      Pitch of a 3D twist
 |
 |      :return: the pitch of the twist
 |      :rtype: float
 |
 |      ``X.pitch()`` is the pitch of the twist as a scalar in units of distance
 |      per radian.
 |
 |      If we consider the twist as a screw, this is the distance of
 |      translation along the screw axis for a one radian rotation about the
 |      screw axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
 |          >>> S = Twist3(T)
 |          >>> S.pitch
 |
 |  pole
 |      Pole of a 3D twist
 |
 |      :return: the pole of the twist
 |      :rtype: ndarray(3)
 |
 |      ``X.pole()`` is a point on the twist axis. For a pure translation
 |      this point is at infinity.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import SE3, Twist3
 |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
 |          >>> S = Twist3(T)
 |          >>> S.pole
 |
 |  shape
 |      Shape of the object's internal array representation
 |
 |      :return: (6,)
 |      :rtype: tuple
 |
 |  v
 |      Moment vector of twist
 |
 |      :return: Moment vector
 |      :rtype: ndarray(3)
 |
 |      ``X.v`` is a 3-vector representing the moment vector of the twist.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> t = Twist3([1, 2, 3, 4, 5, 6])
 |          >>> t.v
 |
 |  w
 |      Direction vector of twist
 |
 |      :return: Direction vector
 |      :rtype: ndarray(3)
 |
 |      ``X.w`` is a 3-vector representing the direction vector of the twist.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> t = Twist3([1, 2, 3, 4, 5, 6])
 |          >>> t.w
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from BaseTwist:
 |
 |  __eq__(left, right)
 |      Overloaded ``==`` operator (superclass method)
 |
 |      :return: Equality of two operands
 |      :rtype: bool or list of bool
 |
 |      ``S1 == S2`` is True if ``S1` is elementwise equal to ``S2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist2
 |          >>> S1 = Twist3([1,2,3,4,5,6])
 |          >>> S2 = Twist3([1,2,3,4,5,6])
 |          >>> S1 == S2
 |          >>> S2 = Twist3([1,2,3,4,5,7])
 |          >>> S1 == S2
 |
 |      :seealso: :func:`__ne__`
 |
 |  __ne__(left, right)
 |      Overloaded ``!=`` operator (superclass method)
 |
 |      :rtype: bool
 |
 |      ``S1 == S2`` is True if ``S1` is not elementwise equal to ``S2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S1 = Twist3([1,2,3,4,5,6])
 |          >>> S2 = Twist3([1,2,3,4,5,6])
 |          >>> S1 != S2
 |          >>> S2 = Twist3([1,2,3,4,5,7])
 |          >>> S1 != S2
 |
 |      :seealso: :func:`__ne__`
 |
 |  __truediv__(left, right)
 |
 |  inv(self)
 |      Inverse of Twist (superclass method)
 |
 |      :return: inverse
 |      :rtype: Twist instance
 |
 |      Compute the inverse of each of the values within the twist instance.
 |      The inverse is the negative of the twist vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3(SE3.Rand())
 |          >>> S
 |          >>> S.inv()
 |          >>> S * S.inv()
 |
 |  prod(self)
 |      Product of twists (superclass method)
 |
 |      :return: Product of elements
 |      :rtype: Twist2 or Twist3
 |
 |      For a twist instance with N values return the matrix product of those
 |      elements :math:`\prod_i=0^{N-1} S_i`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3.Rx([0.2, 0.3, 0.4])
 |          >>> len(S)
 |          >>> S.prod()
 |          >>> Twist3.Rx(0.9)
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from BaseTwist:
 |
 |  S
 |      Twist as a vector (superclass property)
 |
 |      :return: Twist vector
 |      :rtype: ndarray(N)
 |
 |      - ``X.S`` is a 3-vector if X is a ``Twist2`` instance, and a 6-vector if
 |        X is a ``Twist3`` instance.
 |
 |      .. note::
 |
 |          - the vector is the unique elements of the se(N) representation.
 |          - the vector is sometimes referred to as the twist coordinate vector.
 |          - if ``len(X)`` > 1 then return a list of vectors.
 |
 |  isprismatic
 |      Test for prismatic twist (superclass property)
 |
 |      :return: Whether twist is purely prismatic
 |      :rtype: bool
 |
 |      A prismatic twist has :math:`\vec{\omega} = 0`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.UnitPrismatic([1,2,3])
 |          >>> x.isprismatic
 |          >>> x = Twist3.UnitRevolute([1,2,3], [4,5,6])
 |          >>> x.isprismatic
 |
 |  isrevolute
 |      Test for revolute twist (superclass property)
 |
 |      :return: Whether twist is purely revolute
 |      :rtype: bool
 |
 |      A revolute twist has :math:`\vec{v} = 0`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> x = Twist3.UnitPrismatic([1,2,3])
 |          >>> x.isrevolute
 |          >>> x = Twist3.UnitRevolute([1,2,3], [0,0,0])
 |          >>> x.isrevolute
 |
 |  isunit
 |      Test for unit twist (superclass property)
 |
 |      :return: Whether twist is a unit-twist
 |      :rtype: bool
 |
 |      A unit twist is one with a norm of 1, ie. :math:`\| S \| = 1`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Twist3
 |          >>> S = Twist3([1,2,3,4,5,6])
 |          >>> S.isunit()
 |          >>> S = Twist3.UnitRevolute([1,2,3], [4,5,6])
 |          >>> S.isunit()
 |
 |  theta
 |      Twist angle (superclass method)
 |
 |      :return: magnitude of rotation (1x1) about the twist axis in radians
 |      :rtype: float
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes inherited from BaseTwist:
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __add__(self, other)
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __iadd__(self, other)
 |
 |  __imul__(self, n)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.UnitDualQuaternion
Python Library Documentation: class UnitDualQuaternion in module spatialmath.DualQuaternion

class UnitDualQuaternion(DualQuaternion)
 |  UnitDualQuaternion(real=None, dual=None)
 |
 |  [summary]
 |
 |  :param DualQuaternion: [description]
 |  :type DualQuaternion: [type]
 |
 |
 |  .. warning:: Unlike the other spatial math classes, this class does not
 |    (yet) support multiple values per object.
 |
 |  :seealso: :func:`UnitDualQuaternion`
 |
 |  Method resolution order:
 |      UnitDualQuaternion
 |      DualQuaternion
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  SE3(self) -> 'SE3'
 |      Convert unit dual quaternion to SE(3) matrix
 |
 |      :return: SE(3) matrix
 |      :rtype: SE3
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, SE3
 |          >>> T = SE3.Rand()
 |          >>> print(T)
 |          >>> d = UnitDualQuaternion(T)
 |          >>> print(d)
 |          >>> print(d.T)
 |
 |  __init__(self, real=None, dual=None)
 |      Create new unit dual quaternion
 |
 |      :param real: real quaternion or SE(3) matrix
 |      :type real: Quaternion, UnitQuaternion or SE3
 |      :param dual: dual quaternion
 |      :type dual: Quaternion or UnitQuaternion
 |
 |      - ``UnitDualQuaternion(real, dual)`` is a new unit dual quaternion with
 |        real and dual parts as specified.
 |      - ``UnitDualQuaternion(T)`` is a new unit dual quaternion equivalent to
 |        the rigid-body motion described by the SE3 value ``T``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitDualQuaternion, SE3
 |          >>> T = SE3.Rand()
 |          >>> print(T)
 |          >>> d = UnitDualQuaternion(T)
 |          >>> print(d)
 |          >>> type(d)
 |
 |      The dual number is stored internally as two quaternion, respectively
 |      called ``real`` and ``dual``.  For a unit dual quaternion they are
 |      respectively:
 |
 |      .. math::
 |
 |          \q_r &\sim \mat{R}
 |
 |          q_d &= \frac{1}{2} q_t \q_r
 |
 |      where :math:`\mat{R}` is the rotational part of the rigid-body motion
 |      and :math:`q_t` is a pure quaternion formed from the translational part
 |      :math:`t`.
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from DualQuaternion:
 |
 |  __add__(left, right: 'DualQuaternion') -> 'Self'
 |      Sum of two dual quaternions
 |
 |      :return: Product
 |      :rtype: DualQuaternion
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d + d
 |
 |  __mul__(left, right: 'Self') -> 'Self'
 |      Product of dual quaternion
 |
 |      - ``dq1 * dq2`` is a dual quaternion representing the product of
 |        ``dq1`` and ``dq2``.  If both are unit dual quaternions, the product
 |        will be a unit dual quaternion.
 |      - ``dq * p`` transforms the point ``p`` (3) by the unit dual quaternion
 |        ``dq``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d * d
 |
 |  __repr__(self) -> 'str'
 |      Return repr(self).
 |
 |  __str__(self) -> 'str'
 |      String representation of dual quaternion
 |
 |      :return: compact string representation
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> str(d)
 |
 |  __sub__(left, right: 'DualQuaternion') -> 'Self'
 |      Difference of two dual quaternions
 |
 |      :return: Product
 |      :rtype: DualQuaternion
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d - d
 |
 |  conj(self) -> 'Self'
 |      Conjugate of dual quaternion
 |
 |      :return: Conjugate
 |      :rtype: DualQuaternion
 |
 |      There are several conjugates defined for a dual quaternion. This one
 |      mirrors conjugation for a regular quaternion.  For the dual quaternion
 |      :math:`(p, q)` it returns :math:`(p^*, q^*)`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.conj()
 |
 |  matrix(self) -> 'R8x8'
 |      Dual quaternion as a matrix
 |
 |      :return: Matrix represensation
 |      :rtype: ndarray(8,8)
 |
 |      Dual quaternion multiplication can also be written as a matrix-vector
 |      product.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.matrix()
 |          >>> d.matrix() @ d.vec
 |          >>> d * d
 |
 |  norm(self) -> 'Tuple[float, float]'
 |      Norm of a dual quaternion
 |
 |      :return: Norm as a dual number
 |      :rtype: 2-tuple
 |
 |      The norm of a ``UnitDualQuaternion`` is unity, represented by the dual
 |      number (1,0).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.norm()  # norm is a dual number
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from DualQuaternion:
 |
 |  Pure(x: 'ArrayLike3') -> 'Self'
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from DualQuaternion:
 |
 |  vec
 |      Dual quaternion as a vector
 |
 |      :return: Vector represensation
 |      :rtype: ndarray(8)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import DualQuaternion, Quaternion
 |          >>> d = DualQuaternion(Quaternion([1,2,3,4]), Quaternion([5,6,7,8]))
 |          >>> d.vec
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from DualQuaternion:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
spatialmath-python.UnitQuaternion
Python Library Documentation: class UnitQuaternion in module spatialmath.quaternion

class UnitQuaternion(Quaternion)
 |  UnitQuaternion(s: 'Any' = None, v=None, norm: 'Optional[bool]' = True, check: 'Optional[bool]' = True)
 |
 |  Unit quaternion class
 |
 |  A unit quaternion can be considered an ordered pair :math:`(s, \vec{v})`
 |  where :math:`s \in \mathbb{R}` is the *scalar* part and :math:`\vec{v} = (v_x, v_y, v_z) \in \mathbb{R}^3`
 |  is the *vector* part and is often written as
 |
 |  .. math:: \q = s \langle v_x, v_y, v_z \rangle
 |
 |  and subject to a unit-length constraint :math:`s^2+v_x^2+v_y^2+v_z^2 = 1`.
 |
 |  A unit-quaternion can be considered as a rotation :math:`\theta` about the
 |  vector :math:`\vec{v}`, so the unit quaternion can also be
 |  written as
 |
 |  .. math:: \q = \cos \frac{\theta}{2} \sin \frac{\theta}{2} <v_x v_y v_z>
 |
 |  The quaternion :math:`\q` and :math:`-\q` represent the equivalent rotation, and this is referred to
 |  as a double mapping.
 |
 |  .. inheritance-diagram:: spatialmath.quaternion.UnitQuaternion
 |      :top-classes: collections.UserList
 |      :parts: 1
 |
 |  The ``UnitQuaternion`` class inherits many methods from the ``Quaternion`` class
 |
 |  Method resolution order:
 |      UnitQuaternion
 |      Quaternion
 |      spatialmath.baseposelist.BasePoseList
 |      collections.UserList
 |      collections.abc.MutableSequence
 |      collections.abc.Sequence
 |      collections.abc.Reversible
 |      collections.abc.Collection
 |      collections.abc.Sized
 |      collections.abc.Iterable
 |      collections.abc.Container
 |      abc.ABC
 |      builtins.object
 |
 |  Methods defined here:
 |
 |  SE3(self) -> 'SE3'
 |      Unit quaternion as SE3 instance
 |
 |      :return: an SE(3) representation
 |      :rtype: SE3 instance
 |
 |      ``q.SE3()`` is an ``SE3`` instance representing the same rotation
 |      as the unit quaternion ``q`` and with zero translation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> UQ.Rz(0.3).SE3()
 |
 |  SO3(self) -> 'SO3'
 |      Unit quaternion as SO3 instance
 |
 |      :return: an SO(3) representation
 |      :rtype: SO3 instance
 |
 |      ``q.SO3()`` is an ``SO3`` instance representing the same rotation
 |      as the unit quaternion ``q``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> UQ.Rz(0.3).SO3()
 |
 |  __eq__(left, right: 'UnitQuaternion') -> 'bool'
 |      Overloaded ``==`` operator
 |
 |      :rtype: bool
 |
 |      ``q1 == q2`` is True if ``q1`` is elementwise equal to ``q2`` and accounts for the
 |      double mapping. Supports broadcasting.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q1 = UQ.Rx(0.3)
 |          >>> q2 = UQ.Ry(0.3)
 |          >>> q1 == q1
 |          >>> q1 == (-q1)
 |          >>> q1 == q2
 |          >>> UQ([q1, q2]) == q1
 |          >>> UQ([q1, q2]) == q2
 |          >>> UQ([q1, q2]) == UQ([q1, q2])
 |
 |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
 |
 |  __imul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
 |      Multiply unit quaternion in place
 |
 |      :return: product
 |      :rtype: UnitQuaternion, Quaternion
 |      :raises: ValueError
 |
 |      Multiplies a quaternion in place. If the right operand is a list,
 |      the result will be a list.
 |
 |      Example::
 |
 |          >>> q = UQ.Rx(0.3)
 |          >>> q *= UQ.Rx(0.3)
 |          >>> q
 |
 |      :seealso: :func:`__mul__`
 |
 |  __init__(self, s: 'Any' = None, v=None, norm: 'Optional[bool]' = True, check: 'Optional[bool]' = True)
 |      Construct a UnitQuaternion instance
 |
 |      :param norm: explicitly normalize the quaternion [default True]
 |      :type norm: bool
 |      :param check: explicitly check validity of argument [default True]
 |      :type check: bool
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |      :raises: ValueError
 |
 |      - ``UnitQuaternion()`` constructs the identity quaternion 1<0,0,0>
 |      - ``UnitQuaternion(s, v)`` constructs a unit quaternion with specified
 |        real ``s`` and ``v`` vector parts. ``v`` is a 3-vector given as a
 |        list, tuple, or ndarray(3). If ``norm`` is True the resulting
 |        quaternion is normalized.
 |      - ``UnitQuaternion(v)`` constructs a unit quaternion with specified
 |        elements from ``v`` which is a 4-vector given as a list, tuple, or ndarray(4). Also known
 |        as the Euler parameters.
 |      - ``UnitQuaternion(M)`` construct a new unit quaternion with ``N`` values where ``Q`` is a Nx4 NumPy array
 |        whose rows are the quaternion in vector form
 |      - ``UnitQuaternion(R)`` constructs a unit quaternion from an SO(3)
 |        rotation matrix given as a ndarray(3,3). If ``check`` is True
 |        test the rotation submatrix for orthogonality.
 |      - ``UnitQuaternion(X)`` constructs a unit quaternion from the rotational
 |        part of ``X`` which is an SO3 or SE3 instance.  If len(X) > 1 then
 |        the resulting unit quaternion is of the same length.
 |      - ``UnitQuaternion([q1, q2 .. qN])`` construct a new unit quaternion with ``N`` values where each element is a 4-vector
 |      - ``UnitQuaternion([Q1, Q2 .. QN])`` construct a new unit quaternion with ``N`` values where each element is a UnitQuaternion instance
 |      - ``UnitQuaternion([X1, X2 .. XN])`` construct a new unit quaternion with ``N`` values where each element is an SO3 or SE3 instance
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q = UQ()
 |          >>> q         # repr()
 |          >>> print(q)  # str()
 |
 |  __matmul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
 |      Overloaded @ operator
 |
 |      :return: product :rtype: UnitQuaternion
 |
 |      - ``q1 @ q2`` is the Hamilton product of ``q1`` and ``q2``, both unit
 |        quaternions, followed by explicit normalization.
 |
 |      - `` q1 @= q2`` as above.
 |
 |      .. note:: This operator is functionally equivalent to ``*`` but is more
 |          costly.  It is useful for cases where a pose is incrementally update
 |          over many cycles.
 |
 |  __mul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
 |      Multiply unit quaternion
 |
 |      :return: product
 |      :rtype: Quaternion, UnitQuaternion
 |      :raises: ValueError
 |
 |      ==============   ==============   ==============  ================
 |                 Multiplicands                   Product
 |      -------------------------------   --------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ================
 |      UnitQuaternion   Quaternion       Quaternion      Hamilton product
 |      UnitQuaternion   UnitQuaternion   UnitQuaternion  Hamilton product
 |      UnitQuaternion   scalar           Quaternion      scalar product
 |      UnitQuaternion   3-vector         3-vector        vector rotation
 |      UnitQuaternion   3xN array        3xN array       vector rotations
 |      ==============   ==============   ==============  ================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rx(0.3) * UQ.Rx(0.4))
 |          >>> print(UQ.Rx(0.3) * 2)
 |          >>> print(UQ.Rx(0.3) * [1, 2, 3])
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``prod = left * right``
 |       1      N       N    ``prod[i] = left * right[i]``
 |       N      1       N    ``prod[i] = left[i] * right``
 |       N      N       N    ``prod[i] = left[i] * right[i]``
 |       N      M       n/a    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      A scalar of length N is a list, tuple or numpy array.
 |      A 3-vector of length N is a 3xN numpy array, where each column is
 |      a 3-vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rx(0.3) * UQ.Rx(0.4))
 |          >>> q = UQ.Rx(0.3)
 |          >>> q *= UQ.Rx(0.4))
 |          >>> print(q)
 |          >>> print(UQ.Rx(0.3) * UQ.Rx([0.4, 0.6]))
 |          >>> print(UQ.Rx([0.3, 0.6]) * UQ.Rx(0.3))
 |          >>> print(UQ.Rx([0.3, 0.6]) * UQ.Rx([0.3, 0.6]))
 |
 |      :seealso: :meth:`Quaternion.__mul__`
 |
 |  __ne__(left, right: 'UnitQuaternion') -> 'bool'
 |      Overloaded ``!=`` operator
 |
 |      :rtype: bool
 |
 |      ``q1 != q2`` is True if ``q1`` is elementwise not equal to ``q2`` and accounts for the
 |      double mapping. Supports broadcasting.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q1 = UQ.Rx(0.3)
 |          >>> q2 = UQ.Ry(0.3)
 |          >>> q1 != q1
 |          >>> q1 != (-q1)
 |          >>> q1 != q2
 |          >>> UQ([q1, q2]) == q1
 |          >>> UQ([q1, q2]) == q2
 |          >>> UQ([q1, q2]) == UQ([q1, q2])
 |
 |      :seealso: :func:`__eq__` :func:`~spatialmath.base.quaternions.qisequal`
 |
 |  __truediv__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
 |      Overloaded ``/`` operator
 |
 |      :rtype: Quaternion or UnitQuaternion
 |
 |      - ``q1 / q2`` is equivalent to ``q1 * q1.inv()``.
 |      - ``q / s`` performs elementwise division of the elements of ``q`` by
 |        ``s``. This is not a group operation so the result will be a
 |        Quaternion.
 |
 |      ==============   ==============   ==============  ===========================
 |                 Multiplicands                   Quotient
 |      -------------------------------   -------------------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ===========================
 |      UnitQuaternion   UnitQuaternion   UnitQuaternion  Hamilton product by inverse
 |      UnitQuaternion   scalar           Quaternion      element-wise division
 |      ==============   ==============   ==============  ===========================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rx(0.3) / UQ.Rx(0.3))
 |          >>> print(UQ.Rx(0.3) / 2)
 |
 |      For pose composition either or both operands may hold more than one value which
 |      results in the composition holding more than one value according to:
 |
 |      =========   ==========   ====  =====================================
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  =====================================
 |       1          1             1    ``quo = left * right.inv()``
 |       1          M             M    ``quo[i] = left * right[i].inv()``
 |       N          1             M    ``quo[i] = left[i] * right.inv()``
 |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
 |      =========   ==========   ====  =====================================
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rx(0.3) / UQ.Rx(0.3))
 |          >>> print(UQ.Rx([0.3, 0.6]) / UQ.Rx(0.3))
 |          >>> print(UQ.Rx(0.3) / UQ.Rx([0.3, 0.6]))
 |          >>> print(UQ.Rx([0.3, 0.6]) / UQ.Rx([0.3, 0.6]))
 |
 |  angdist(self, other: 'UnitQuaternion', metric: 'Optional[int]' = 3) -> 'float'
 |      Angular distance metric between unit quaternions
 |
 |      :param other: second unit quaternion
 |      :type other: UnitQuaternion instance
 |      :param metric: metric, default is 3
 |      :type metric: int
 |      :raises TypeError: if other is not a UnitQuaternion
 |      :return: angle in radians
 |      :rtype: float
 |
 |      ``q1.angdist(q2)`` is the geodesic norm, or geodesic distance between two
 |      unit quaternions.  We can consider it as the angle between two quaternions.
 |
 |      Several metrics are supported:
 |
 |      ======   ===============================================================
 |      Metric   Details
 |      ======   ===============================================================
 |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
 |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
 |      3        :math:`2 \tan^{-1} \| \q_1 \pm \q_2\| / \|\q_1 \mp \q_2\| \in [0, \pi/2]`
 |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
 |      ======   ===============================================================
 |
 |      Metric 3 computes the sum and difference of the quaternions and uses
 |      the largest value in the denominator.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion
 |          >>> q1 = UnitQuaternion.Rx(0.3)
 |          >>> q2 = UnitQuaternion.Ry(0.3)
 |          >>> print(q1.angdist(q1))
 |          >>> print(q1.angdist(q2))
 |
 |      .. note::
 |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
 |            numeric errors which push the argument of ``acos()`` marginally
 |            outside its domain [0, 1].
 |          - metrics 2 and 3 are equivalent, but 3 is more robust
 |          - SMTB-MATLAB uses metric 3 for UnitQuaternion.angle()
 |          - MATLAB's quaternion.dist() uses metric 4
 |
 |  angvec(self, unit: 'Optional[str]' = 'rad') -> 'Tuple[float, R3]'
 |      Unit quaternion as angle and rotation vector
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param check: check that rotation matrix is valid
 |      :type check: bool
 |      :return: :math:`(\theta, {\bf v})`
 |      :rtype: float, ndarray(3)
 |
 |      ``q.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
 |      angle and a rotation axis which is equivalent to the rotation of
 |      the unit quaternion ``q``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> UQ.Rz(0.3).angvec()
 |
 |      :seealso: :meth:`Quaternion.AngVec` :meth:`UnitQuaternion.log` :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  animate(self, *args: 'List', **kwargs)
 |      Plot unit quaternion as an animated coordinate frame
 |
 |      :param start: initial pose, defaults to null/identity
 |      :type start: UnitQuaternion
 |      :param `**kwargs`: plotting options
 |
 |      - ``q.animate()`` displays the orientation ``q`` as a coordinate frame moving
 |        from the origin in either 3D.  There are
 |        many options, see the links below.
 |      - ``q.animate(*args, start=q1)`` displays the orientation ``q`` as a coordinate
 |        frame moving from orientation ``q11``, in 3D.  There are
 |        many options, see the links below.
 |
 |      Example::
 |
 |          >>> X = UQ.Rx(0.3)
 |          >>> X.animate(frame='A', color='green')
 |          >>> X.animate(start=UQ.Ry(0.2))
 |
 |      :see :func:`~spatialmath.base.transforms3d.tranimate` :func:`~spatialmath.base.transforms3d.trplot`
 |
 |  dot(self, omega: 'ArrayLike3') -> 'R4'
 |      Rate of change of a unit quaternion in world frame
 |
 |      :param ω: angular velocity in world frame
 |      :type ω: 3-element array_like
 |      :return: rate of change of unit quaternion
 |      :rtype: ndarray(4)
 |
 |      ``q.dot(ω)`` is the rate of change of the elements of the unit quaternion ``q``
 |      which represents the orientation of a body frame with angular velocity ``ω`` in
 |      the world frame.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qdot`
 |
 |  dotb(self, omega: 'ArrayLike3') -> 'R4'
 |      Rate of change of a unit quaternion in body frame
 |
 |      :param ω: angular velocity in body frame
 |      :type ω: 3-element array_like
 |      :return: rate of change of unit quaternion
 |      :rtype: ndarray(4)
 |
 |      ``q.dotb(ω)`` is the rate of change of the elements of the unit quaternion ``q``
 |      which represents the orientation of a body frame with angular velocity ``ω`` in
 |      the body frame.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qdotb`
 |
 |  eul(self, unit: 'Optional[str]' = 'rad') -> 'Union[R3, RNx3]'
 |      Unit quaternion as Euler angles
 |
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of Euler angles
 |      :rtype: ndarray(3)
 |
 |      ``q.eul`` is the Euler angle representation of the rotation.  Euler angles are
 |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
 |      rotations about the Z, Y, Z axes respectively.
 |
 |      If ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(N,3)
 |
 |      - ndarray with shape=(3,), if len(R) == 1
 |      - ndarray with shape=(N,3), if len(R) = N > 1
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> UQ.Rz(0.3).eul()
 |          >>> UQ.Ry([0.3, 0.4]).eul()
 |
 |      :seealso: :meth:`SE3.Eul` :func:`~spatialmath.base.transforms3d.tr2eul`
 |
 |  increment(self, w: 'ArrayLike3', normalize: 'Optional[bool]' = False) -> 'None'
 |      Quaternion incremental update
 |
 |      :param w: angular displacement, Euler vector
 |      :type w: array_like(3)
 |      :param normalize: normalize the result, defaults to False
 |      :type normalize: bool, optional
 |
 |      .. note:: The object state is updated
 |
 |  interp(self, end: 'UnitQuaternion', s: 'float' = 0, shortest: 'Optional[bool]' = False) -> 'UnitQuaternion'
 |      Interpolate between two unit quaternions
 |
 |      :param end: final unit quaternion
 |      :type end: UnitQuaternion
 |      :param shortest: Take the shortest path along the great circle
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :return: interpolated unit quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``q0.interp(q1, s)`` is a unit quaternion that is interpolated between
 |        ``q0`` when s=0 and ``q1`` when s=1. Spherical linear interpolation
 |        (slerp) is used.  If ``s`` is an ndarray(n) then the result will be
 |        a UnitQuaternion with n values.
 |
 |      - ``q0.interp(q1, N)`` interpolate between ``q0`` and ``q1`` in ``N``
 |        steps.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q1 = UQ.Rx(0.3); q2 = UQ.Rz(-0.4)
 |          >>> print(q1)
 |          >>> print(q2)
 |          >>> q1.interp(q2, 0)    # this is q1
 |          >>> q1.interp(q2, 1,)   # this is q2
 |          >>> q1.interp(q2, 0.5)  # this is in between
 |          >>> q = q1.interp(q2, 11)  # in 11 steps
 |          >>> len(q)
 |          >>> q[0]                # this is q1
 |          >>> q[5]                # this is in between
 |
 |      .. note:: values of ``s`` are silently clipped to the range [0, 1]
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qslerp`
 |
 |  interp1(self, s: 'float' = 0, shortest: 'Optional[bool]' = False) -> 'UnitQuaternion'
 |      Interpolate a unit quaternion
 |
 |      :param shortest: Take the shortest path along the great circle
 |      :param s: interpolation coefficient, range 0 to 1, or number of steps
 |      :type s: array_like or int
 |      :return: interpolated unit quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``q.interp1(s)`` is a unit quaternion that is interpolated between
 |        identity when s=0 and ``q`` when s=1. Spherical linear interpolation
 |        (slerp) is used.  If ``s`` is an ndarray(n) then the result will be
 |        a UnitQuaternion with n values.
 |
 |      - ``q.interp1(N)`` interpolate between identity and ``q1`` in ``N``
 |        steps.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q = UQ.Rx(0.3)
 |          >>> print(q)
 |          >>> q.interp1(0)    # this is identity
 |          >>> q.interp1(1)    # this is q
 |          >>> q.interp1(0.5)  # this is in between
 |          >>> qi = q.interp1(11)  # in 11 steps
 |          >>> len(qi)
 |          >>> qi[0]                # this is q1
 |          >>> qi[5]                # this is in between
 |
 |      .. note:: values of ``s`` are silently clipped to the range [0, 1]
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qslerp`
 |
 |  inv(self) -> 'UnitQuaternion'
 |      Inverse of unit quaternion
 |
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      ``q.inv()`` is the inverse of the unit-quaternion.  This is a group operation
 |      and the product of the unit-quaternion and its inverse is the identity quaternion.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion
 |          >>> print(UQ.Rx(0.3).inv())
 |          >>> print(UQ.Rx(0.3).inv() * UQ.Rx(0.3))
 |          >>> print(UQ.Rx([0.3, 0.6]).inv())
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qinv`
 |
 |  plot(self, *args: 'List', **kwargs)
 |      Plot unit quaternion as a coordinate frame
 |
 |      :param `**kwargs`: plotting options
 |
 |      - ``q.plot()`` displays the orientation ``q`` as a coordinate frame in 3D.
 |        There are many options, see the links below.
 |
 |      Example::
 |
 |          >>> q = UQ.Rx(0.3)
 |          >>> q.plot(frame='A', color='green')
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`
 |
 |  rpy(self, unit: 'Optional[str]' = 'rad', order: 'Optional[str]' = 'zyx') -> 'Union[R3, RNx3]'
 |      Unit quaternion as roll-pitch-yaw angles
 |
 |      :param order: angle sequence order, default to 'zyx'
 |      :type order: str
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: 3-vector of roll-pitch-yaw angles
 |      :rtype: ndarray(3) or ndarray(n,3)
 |
 |      ``q.rpy`` is the roll-pitch-yaw angle representation of the 3D rotation.  The angles are
 |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
 |      specified by ``order``:
 |
 |          - 'zyx' [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
 |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
 |            and y-axis sideways.
 |          - 'xyz', rotate by yaw about the x-axis, then by pitch about the new y-axis,
 |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
 |            and y-axis between the gripper fingers.
 |          - 'yxz', rotate by yaw about the y-axis, then by pitch about the new x-axis,
 |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
 |            to the optic axis and x-axis parallel to the pixel rows.
 |
 |      If ``len(x)`` is:
 |
 |      - 1, return an ndarray with shape=(3,)
 |      - N>1, return ndarray with shape=(N,3)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> UQ.Rx(0.3).rpy()
 |          >>> UQ.Rz([0.2, 0.3]).rpy()
 |
 |      :seealso: :meth:`SE3.RPY` :func:`~spatialmath.base.transforms3d.tr2rpy`
 |
 |  ----------------------------------------------------------------------
 |  Class methods defined here:
 |
 |  AngVec(theta: 'float', v: 'ArrayLike3', *, unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from rotation angle and axis
 |
 |      :param theta: rotation
 |      :type theta: float
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param v: rotation axis, 3-vector
 |      :type v: array_like
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      ``UnitQuaternion.AngVec(θ, v)`` is a unit quaternion that describes the 3D rotation
 |      defined by a rotation of ``θ`` about the 3-vector ``v``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.AngVec(0, [1,0,0]))
 |          >>> print(UQ.AngVec(90, [1,0,0], unit='deg'))
 |
 |      .. note:: :math:`\theta = 0` the result in an identity quaternion, otherwise
 |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
 |
 |      :seealso: :meth:`UnitQuaternion.angvec` :meth:`UnitQuaternion.exp` :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  Eul(*angles: 'List[float]', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from Euler angles
 |
 |      :param 𝚪: 3-vector of Euler angles
 |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion.Eul(𝚪)`` is a unit quaternion that describes the 3D
 |        rotation defined by a 3-vector of Euler angles :math:`\Gamma = (\phi,
 |        \theta, \psi)` which correspond to consecutive rotations about the Z,
 |        Y, Z axes respectively.
 |
 |      - ``UnitQuaternion.Eul(φ, θ, ψ)`` as above but the angles are provided
 |        as three scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Eul([0.1, 0.2, 0.3]))
 |
 |      :seealso: :meth:`UnitQuaternion.RPY` :meth:`SE3.eul` :meth:`SE3.Eul` :meth:`~spatialmath.base.transforms3d.eul2r`
 |
 |  EulerVec(w: 'ArrayLike3') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from an Euler rotation vector
 |
 |      :param ω: rotation axis
 |      :type ω: 3-element array_like
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      ``UnitQuaternion.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
 |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
 |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.EulerVec([0.5,0,0]))
 |
 |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
 |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
 |
 |      :seealso: :meth:`SE3.angvec` :func:`~spatialmath.base.transforms3d.angvec2r`
 |
 |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from two vectors
 |
 |      :param o: 3-vector parallel to Y- axis
 |      :type o: array_like
 |      :param a: 3-vector parallel to the Z-axis
 |      :type a: array_like
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      ``UnitQuaternion.OA(O, A)`` is a unit quaternion that describes the 3D rotation defined in terms of
 |      vectors parallel to the Y- and Z-axes of its reference frame.  In robotics these axes are
 |      respectively called the orientation and approach vectors defined such that
 |      R = [N O A] and N = O x A.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.OA([0,0,-1], [0,1,0]))
 |
 |      .. note::
 |
 |          - Only the ``A`` vector is guaranteed to have the same direction in the resulting
 |          rotation matrix
 |          - ``O`` and ``A`` do not have to be unit-length, they are normalized
 |          - ``O`` and ``A` do not have to be orthogonal, so long as they are not parallel
 |
 |      :seealso: :func:`~spatialmath.base.transforms3d.oa2r`
 |
 |  RPY(*angles, order: 'Optional[str]' = 'zyx', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from roll-pitch-yaw angles
 |
 |      :param 𝚪: 3-vector of roll-pitch-yaw angles
 |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :param unit: rotation order: 'zyx' [default], 'xyz', or 'yxz'
 |      :type unit: str
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion.RPY(𝚪)`` is a unit quaternion that describes the 3D
 |        rotation defined by a  3-vector of roll, pitch, yaw angles
 |        :math:`\Gamma = (r, p, y)` which correspond to successive rotations
 |        about the axes specified by ``order``:
 |
 |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch
 |            about the new y-axis, then by roll about the new x-axis.
 |            Convention for a mobile robot with x-axis forward and y-axis
 |            sideways.
 |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the
 |            new y-axis, then by roll about the new z-axis. Convention for a
 |            robot gripper with z-axis forward and y-axis between the gripper
 |            fingers.
 |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the
 |            new x-axis, then by roll about the new z-axis. Convention for a
 |            camera with z-axis parallel to the optic axis and x-axis parallel
 |            to the pixel rows.
 |
 |
 |      - ``UnitQuaternion.RPY(⍺, β, 𝛾)`` as above but the angles are provided
 |        as three scalars.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.RPY([0.1, 0.2, 0.3]))
 |
 |      :seealso: :meth:`UnitQuaternion.Eul` :meth:`SE3.rpy` :meth:`SE3.RPY` :func:`~spatialmath.base.transforms3d.rpy2r`
 |
 |  Rand(N: 'int' = 1, *, theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'UnitQuaternion'
 |      Construct a new random unit quaternion
 |
 |      :param N: number of random rotations
 |      :type N: int
 |      :param theta_range: angular magnitude range [min,max], defaults to None -> [0,pi].
 |      :type xrange: 2-element sequence, optional
 |      :param unit: angular units: 'rad' [default], or 'deg'
 |      :type unit: str
 |      :return: random unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion.Rand()`` is a uniformly distributed random unit quaternion value.
 |      - ``SO3.Rand(N)`` is a unit quaternion instance containing a sequence of N random unit quaternion
 |        values.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rand())
 |          >>> print(UQ.Rand(3))
 |
 |      :seealso: :meth:`UnitQuaternion.Rand`
 |
 |  Rx(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a UnitQuaternion object representing rotation about the X-axis
 |
 |      :arg θ: rotation angle
 |      :type θ: array_like
 |      :arg unit: rotation unit 'rad' [default] or 'deg'
 |      :type unit: str
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
 |        rotation of ``θ`` radians about the X-axis.
 |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
 |        rotation of ``θ`` degrees about the X-axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rx(0.3))
 |          >>> print(UQ.Rx([0, 0.3, 0.6]))
 |
 |  Ry(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a UnitQuaternion object representing rotation about the Y-axis
 |
 |      :arg θ: rotation angle
 |      :type θ: array_like
 |      :arg unit: rotation unit 'rad' [default] or 'deg'
 |      :type unit: str
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
 |        rotation of ``θ`` radians about the Y-axis.
 |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
 |        rotation of ``θ`` degrees about the Y-axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Ry(0.3))
 |          >>> print(UQ.Ry([0, 0.3, 0.6]))
 |
 |  Rz(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
 |      Construct a UnitQuaternion object representing rotation about the Z-axis
 |
 |      :arg θ: rotation angle
 |      :type θ: array_like
 |      :arg unit: rotation unit 'rad' [default] or 'deg'
 |      :type unit: str
 |      :return: unit-quaternion
 |      :rtype: UnitQuaternion instance
 |
 |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
 |        rotation of ``θ`` radians about the Z-axis.
 |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
 |        rotation of ``θ`` degrees about the Z-axis.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> print(UQ.Rz(0.3))
 |          >>> print(UQ.Rz([0, 0.3, 0.6]))
 |
 |  Vec3(vec: 'ArrayLike3') -> 'UnitQuaternion'
 |      Construct a new unit quaternion from its vector part
 |
 |      :param vec: vector part of unit quaternion
 |      :type vec: 3-element array_like
 |
 |      ``UnitQuaternion.Vec(v)`` is a new unit quaternion with the specified vector part
 |      and the scalar part is
 |
 |      .. math:: s = \sqrt{1 - v_x^2 - v_y^2 - v_z^2}
 |
 |      The unit quaternion will always have a positive scalar part.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q = UQ.Rz(-4)
 |          >>> print(q)
 |          >>> q.vec3
 |          >>> q2 = UQ.Vec3(q.vec3)
 |          >>> print(q2)
 |          >>> q == q2
 |
 |      :seealso: :meth:`UnitQuaternion.vec3`
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  isvalid(x: 'ArrayLike', check: 'Optional[bool]' = True) -> 'bool'
 |      Test if vector is valid unit quaternion
 |
 |      :param x: vector to test
 |      :type x: numpy.ndarray
 |      :arg check: explicitly check vector is unit length [default True]
 |      :type check: bool
 |      :return: True if the matrix has shape (4,).
 |      :rtype: bool
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion
 |          >>> import numpy as np
 |          >>> UnitQuaternion.isvalid(np.r_[1, 0, 0, 0])
 |          >>> UnitQuaternion.isvalid(np.r_[1, 2, 3, 4])
 |
 |  qvmul(qv1: 'ArrayLike3', qv2: 'ArrayLike3') -> 'R3'
 |      Multiply unit quaternions defined by unique vector parts
 |
 |      :param qv1: vector representation of first multiplicand
 |      :type qv1: ndarray(3)
 |      :param qv1: vector representation of second multiplicand
 |      :type qv1: ndarray(3)
 |
 |      ``UnitQuaternion(qv1, qv2)`` is the Hamilton product of two unit quaternions
 |      represented in minimal vector form.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q1 = UQ.Rx(0.3)
 |          >>> q2 = UQ.Ry(-0.3)
 |          >>> qv1 = q1.vec3
 |          >>> qv1
 |          >>> qv2 = q2.vec3
 |          >>> qv = UQ.qvmul(qv1, qv2)
 |          >>> qv
 |          >>> print(UQ.Vec3(qv))
 |          >>> print(UQ.Rx(0.3) * UQ.Ry(-0.3))
 |
 |      :seealso: :meth:`UnitQuaternion.vec3` :meth:`UnitQuaternion.Vec3`
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties defined here:
 |
 |  R
 |      Unit quaternion as a rotation matrix
 |
 |      :return: equivalent rotational matrix
 |      :rtype: ndarray(3,3)
 |
 |      ``q.R`` returns the rotation matrix which describes the equivalent rotation. If ``len(x)`` is:
 |
 |          - 1, return an ndarray with shape=(3,3)
 |          - N>1, return ndarray with shape=(N,3,3)
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q = UQ.Rx(0.3)
 |          >>> q.R
 |          >>> q = UQ.Rx([0.3, 0.4])
 |          >>> q.R
 |
 |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
 |          ``x[i]``. This is different to the MATLAB version where the i'th
 |          rotation matrix is ``x(:,:,i)``.
 |
 |  vec3
 |      Unit quaternion unique vector part
 |
 |      :return: vector part of unit quaternion
 |      :rtype: numpy array, shape=(3,)
 |
 |      ``q.vec3`` is the vector part of a unit quaternion.  If ``q`` has a negative scalar
 |      part we take the vector part of ``-q``, since  ``q`` and ``-q`` represent the
 |      same rotation.
 |
 |      This vector part is a minimal unique representation of the unit quaternion and can be used in
 |      optimization procedures such as bundle adjustment.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import UnitQuaternion as UQ
 |          >>> q = UQ.Rz(-4)
 |          >>> print(q)
 |          >>> q.vec3
 |          >>> q2 = UQ.Vec3(q.vec3)
 |          >>> print(q2)
 |          >>> q == q2
 |
 |      :seealso: :meth:`UnitQuaternion.Vec3`
 |
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |
 |  __abstractmethods__ = frozenset()
 |
 |  __hash__ = None
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from Quaternion:
 |
 |  __add__(left, right: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``+`` operator
 |
 |      :return: sum
 |      :rtype: Quaternion, UnitQuaternion
 |      :raises: ValueError
 |
 |      ==============   ==============   ==============  ===================
 |                 Operands                            Sum
 |      -------------------------------   -----------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ===================
 |      Quaternion       Quaternion       Quaternion      elementwise sum
 |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
 |      Quaternion       scalar           Quaternion      add to each element
 |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
 |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
 |      UnitQuaternion   scalar           Quaternion      add to each element
 |      ==============   ==============   ==============  ===================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``sum = left + right``
 |       1      N       N    ``sum[i] = left + right[i]``
 |       N      1       N    ``sum[i] = left[i] + right``
 |       N      N       N    ``sum[i] = left[i] + right[i]``
 |       N      M       -    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      A scalar of length N is a list, tuple or numpy array.
 |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]) + Quaternion([5,6,7,8])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([1,2,3,4])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  __ipow__(self, n: 'int') -> 'Quaternion'
 |      Overloaded ``=**`` operator
 |
 |      :rtype: Quaternion instance
 |
 |      ``q **= N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
 |      an integer.  If ``N``<0 the result is conjugated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> q **= 2
 |          >>> q
 |          >>> q = Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |          >>> q **= 2
 |          >>> q
 |
 |
 |      :seealso: :func:`__pow__`
 |
 |  __neg__(self) -> 'Quaternion'
 |      Overloaded unary ``-`` operator
 |
 |      :rtype: Quaternion or UnitQuaternion
 |
 |      ``-q`` is a quaternion with all its components negated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> -Quaternion([1,2,3,4])
 |          >>> -Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  __pow__(self, n: 'int') -> 'Quaternion'
 |      Overloaded ``**`` operator
 |
 |      :rtype: Quaternion instance
 |
 |      ``q ** N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
 |      an integer.  If ``N``<0 the result is conjugated.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion([1,2,3,4]) ** 2)
 |          >>> print(Quaternion([1,2,3,4]) ** -1)
 |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) ** 2)
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qpow`
 |
 |  __repr__(self) -> 'str'
 |      Readable representation of pose (superclass method)
 |
 |      :return: readable representation of the pose as a list of arrays
 |      :rtype: str
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> q
 |
 |  __rmul__(right, left: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``*`` operator
 |
 |      :return: product
 |      :rtype: Quaternion
 |      :raises: ValueError
 |
 |      ``s * q`` is the scalar product, where ``s`` is a scalar.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> 2 * Quaternion([1,2,3,4])
 |          >>> 2 * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |      :seealso: :func:`__mul__`
 |
 |  __str__(self) -> 'str'
 |      Pretty string representation of quaternion
 |
 |      :return: readable representation of quaternion
 |      :rtype: str
 |
 |      Format the quaternion elements into a single line format.  For example::
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> print(x)
 |          >> q = UnitQuaternion.Rx(0.3)
 |
 |      Note that unit quaternions are denoted by different delimiters for
 |      the vector part.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  __sub__(left, right: 'Quaternion') -> 'Quaternion'
 |      Overloaded ``-`` operator
 |
 |      :return: difference
 |      :rtype: Quaternion, UnitQuaternion
 |      :raises: ValueError
 |
 |      ==============   ==============   ==============  ==========================
 |                 Operands                          Difference
 |      -------------------------------   ------------------------------------------
 |          left             right            type           result
 |      ==============   ==============   ==============  ==========================
 |      Quaternion       Quaternion       Quaternion      elementwise sum
 |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
 |      Quaternion       scalar           Quaternion      subtract from each element
 |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
 |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
 |      UnitQuaternion   scalar           Quaternion      subtract from each element
 |      ==============   ==============   ==============  ==========================
 |
 |      Any other input combinations result in a ValueError.
 |
 |      Note that left and right can have a length greater than 1 in which case:
 |
 |      ====   =====   ====  ================================
 |      left   right   len     operation
 |      ====   =====   ====  ================================
 |       1      1       1    ``diff = left - right``
 |       1      N       N    ``diff[i] = left - right[i]``
 |       N      1       N    ``diff[i] = left[i] - right``
 |       N      N       N    ``diff[i] = left[i] - right[i]``
 |       N      M       -    ``ValueError``
 |      ====   =====   ====  ================================
 |
 |      A scalar of length N is a list, tuple or numpy array.
 |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]) - Quaternion([5,6,7,8])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([1,2,3,4])
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
 |
 |  conj(self) -> 'Quaternion'
 |      Conjugate of quaternion
 |
 |      :rtype: Quaternion instance
 |
 |      ``q.conj()`` is the quaternion ``q`` with the vector part negated, ie.
 |      :math:`q = s \langle -v_x, -v_y, -v_z \rangle`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion.Pure([1,2,3]).conj())
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qconj`
 |
 |  exp(self, tol: 'float' = 20) -> 'Quaternion'
 |      Exponential of quaternion
 |
 |      :param tol: Tolerance when checking for pure quaternion, in multiples of eps, defaults to 20
 |      :type tol: float, optional
 |      :rtype: Quaternion instance
 |
 |      ``q.exp()`` is the exponential of the quaternion ``q``, ie.
 |
 |      .. math::
 |
 |           e^s \cos \| v \|,  \langle e^s \frac{\vec{v}}{\| \vec{v} \|} \sin \| \vec{v} \| \rangle
 |
 |      For a pure quaternion with vector value :math:`\vec{v}` the the result
 |      is a unit quaternion equivalent to a rotation defined by
 |      :math:`2\vec{v}` intepretted as an Euler vector, that is, parallel to
 |      the axis of rotation and whose norm is the magnitude of rotation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> from math import pi
 |          >>> q = Quaternion([1, 2, 3, 4])
 |          >>> print(q.exp())
 |          >>> q = Quaternion.Pure([pi / 4, 0, 0])
 |          >>> print(q.exp())  # result is a UnitQuaternion
 |          >>> print(q.exp().angvec())
 |
 |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
 |
 |      :seealso: :meth:`Quaternion.log` :meth:`UnitQuaternion.log` :meth:`UnitQuaternion.AngVec` :meth:`UnitQuaternion.EulerVec`
 |
 |  inner(self, other) -> 'float'
 |      Inner product of quaternions
 |
 |      :rtype: float
 |
 |      ``q1.inner(q2)`` is the dot product of the equivalent vectors,
 |      ie. ``numpy.dot(q1.vec, q2.vec)``.
 |      The value of ``q.inner(q)`` is the same as ``q.norm ** 2``.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).inner(Quaternion([5,6,7,8]))
 |          >>> numpy.dot([1,2,3,4], [5,6,7,8])
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qinner`
 |
 |  log(self) -> 'Quaternion'
 |      Logarithm of quaternion
 |
 |      :rtype: Quaternion instance
 |
 |      ``q.log()`` is the logarithm of the quaternion ``q``, ie.
 |
 |      .. math::
 |
 |           \ln \| q \|,  \langle \frac{\vec{v}}{\| \vec{v} \|} \cos^{-1} \frac{s}{\| q \|} \rangle
 |
 |      For a ``UnitQuaternion`` the logarithm is a pure quaternion whose vector
 |      part :math:`\vec{v}` and :math:`\vec{v}/2` is a Euler vector: parallel
 |      to the axis of rotation and whose norm is the magnitude of rotation.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion, UnitQuaternion
 |          >>> from math import pi
 |          >>> q = Quaternion([1, 2, 3, 4])
 |          >>> print(q.log())
 |          >>> q = UnitQuaternion.Rx(pi / 2)
 |          >>> print(q.log())
 |
 |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
 |
 |      :seealso: :meth:`Quaternion.exp` :meth:`Quaternion.log` :meth:`UnitQuaternion.angvec`
 |
 |  norm(self) -> 'float'
 |      Norm of quaternion
 |
 |      :rtype: float
 |
 |      ``q.norm()`` is the norm or length of the quaternion
 |      :math:`\sqrt{s^2 + v_x^2 + v_y^2 + v_z^2}`
 |
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).norm()
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).norm()
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  unit(self) -> 'UnitQuaternion'
 |      Unit quaternion
 |
 |      :rtype: UnitQuaternion instance
 |
 |      ``q.unit()`` is the quaternion ``q`` normalized to have a unit length.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> q = Quaternion([1,2,3,4])
 |          >>> print(q)
 |          >>> print(q.unit())
 |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).unit())
 |
 |      Note that the return type is different, a ``UnitQuaternion``, which is
 |      distinguished by the use of double angle brackets to delimit the
 |      vector part.
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from Quaternion:
 |
 |  Pure(v: 'ArrayLike3') -> 'Quaternion'
 |      Construct a pure quaternion from a vector
 |
 |      :param v: vector
 |      :type v: 3-element array_like
 |
 |      ``Quaternion.Pure(v)`` is a Quaternion with a zero scalar part and the
 |      vector part set to ``v``,
 |      ie. :math:`q = 0 \langle v_x, v_y, v_z \rangle`
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> print(Quaternion.Pure([1,2,3]))
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from Quaternion:
 |
 |  matrix
 |      Matrix equivalent of quaternion
 |
 |      :rtype: Numpy array, shape=(4,4)
 |
 |      ``q.matrix`` is a 4x4 matrix which encodes the arithmetic rules of Hamilton multiplication.
 |      This matrix, multiplied by the 4-vector equivalent of a second quaternion, results in the 4-vector
 |      equivalent of the Hamilton product.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).matrix
 |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])   # Hamilton product
 |          >>> Quaternion([1,2,3,4]).matrix @ Quaternion([5,6,7,8]).vec  # matrix-vector product
 |
 |      :seealso: :func:`~spatialmath.base.quaternions.qmatrix`
 |
 |  s
 |      Scalar part of quaternion
 |
 |      :return: scalar part of quaternion
 |      :rtype: float or numpy.ndarray
 |
 |      ``q.s`` is the scalar part.  If `len(q)` is:
 |
 |          - 1, return a scalar float
 |          - N>1, return a NumPy array shape=(N,) is returned.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).s
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).s
 |
 |  shape
 |      Shape of the object's interal matrix representation
 |
 |      :return: (4,)
 |      :rtype: tuple
 |
 |  v
 |      Vector part of quaternion
 |
 |      :return: vector part of quaternion
 |      :rtype: NumPy ndarray
 |
 |      ``q.v`` is the vector part.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(3,)
 |          - N>1, return a NumPy array shape=(N,3).
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).v
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).v
 |
 |  vec
 |      Quaternion as a vector
 |
 |      :return: quaternion expressed as a 4-vector
 |      :rtype: numpy ndarray, shape=(4,)
 |
 |      ``q.vec`` is the quaternion as a vector.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(4,)
 |          - N>1, return a NumPy array shape=(N,4).
 |
 |      The quaternion coefficients are in the order (s, vx, vy, vz), ie. with
 |      the scalar (real part) first.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).vec
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec
 |
 |  vec_xyzs
 |      Quaternion as a vector
 |
 |      :return: quaternion expressed as a 4-vector
 |      :rtype: numpy ndarray, shape=(4,)
 |
 |      ``q.vec_xyzs`` is the quaternion as a vector.  If `len(q)` is:
 |
 |          - 1, return a NumPy array shape=(4,)
 |          - N>1, return a NumPy array shape=(N,4).
 |
 |      The quaternion coefficients are in the order (vx, vy, vz, s), ie. with
 |      the scalar (real part) last. This is useful when exporting to other
 |      packages like three.js or pybullet.
 |
 |      Example:
 |
 |      .. runblock:: pycon
 |
 |          >>> from spatialmath import Quaternion
 |          >>> Quaternion([1,2,3,4]).vec_xyzs
 |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec_xyzs
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>=value.
 |
 |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
 |      Access value of an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to return
 |      :type i: int
 |      :return: the specific element of the pose
 |      :rtype: Quaternion or UnitQuaternion instance
 |      :raises IndexError: if the element is out of bounds
 |
 |      Note that only a single index is supported, slices are not.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x[1]
 |          >>> len(y)
 |          1
 |          >>> y = x[1:5]
 |          >>> len(y)
 |          4
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self>value.
 |
 |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<=value.
 |
 |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
 |      Return self<value.
 |
 |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
 |      Assign a value to an instance (BasePoseList superclass method)
 |
 |      :param i: index of element to assign to
 |      :type i: int
 |      :param value: the value to insert
 |      :type value: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of assigned value
 |
 |      Assign the argument to an element of the object's internal list of values.
 |      This supports the assignement operator, for example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x[3] = X()   # assign to position 3 in the list
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  append(self, item: 'BasePoseList') -> 'None'
 |      Append a value to an instance (BasePoseList superclass method)
 |
 |      :param x: the value to append
 |      :type x: Quaternion or UnitQuaternion instance
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
 |      Standard constructor support (BasePoseList superclass method)
 |
 |      :param arg: initial value
 |      :param convertfrom: list of classes to accept and convert from
 |      :type: tuple of typles
 |      :param check: check value is valid, defaults to True
 |      :type check: bool
 |      :raises ValueError: bad type passed
 |
 |      The value ``arg`` can be any of:
 |
 |      #. None, an identity value is created
 |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
 |      #. a list whose elements all meet the criteria above
 |      #. an instance of the subclass
 |      #. a list whose elements are all singelton instances of the subclass
 |
 |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
 |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
 |      check of shape is made, if ``check`` is True the numerical value is
 |      inspected) and converted to the required internal format by the
 |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
 |      method for checking.  This mechanism allows equivalent forms to be
 |      passed, ie. 6x1 or 4x4 for an se(3).
 |
 |      If ``self`` is an instance of class ``A``, and an instance of class
 |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
 |      then ``B.A()`` will be invoked to perform the type conversion.
 |
 |      Examples::
 |
 |          SE3()
 |          SE3(np.identity(4))
 |          SE3([np.identity(4), np.identity(4)])
 |          SE3(SE3())
 |          SE3([SE3(), SE3()])
 |          Twist3(SE3())
 |
 |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
 |      Perform binary operation
 |
 |      :param left: left operand
 |      :type left: BasePoseList subclass
 |      :param right: right operand
 |      :type right: BasePoseList subclass, scalar or array
 |      :param op: binary operation
 |      :type op: callable
 |      :param op2: binary operation
 |      :type op2: callable
 |      :param list1: return single array as a list, default True
 |      :type list1: bool
 |      :raises ValueError: arguments are not compatible
 |      :return: list of values
 |      :rtype: list
 |
 |      The is a helper method for implementing binary operation with overloaded
 |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
 |      of ``BasePoseList``.  Each operand has a list of one or more
 |      values and this methods computes a list of result values according to:
 |
 |      =========   ==========   ====  ===================================
 |            Inputs                    Output
 |      ----------------------   -----------------------------------------
 |      len(left)   len(right)   len     operation
 |      =========   ==========   ====  ===================================
 |       1          1             1    ``ret = op(left, right)``
 |       1          M             M    ``ret[i] = op(left, right[i])``
 |       M          1             M    ``ret[i] = op(left[i], right)``
 |       M          M             M    ``ret[i] = op(left[i], right[i])``
 |      =========   ==========   ====  ===================================
 |
 |      The arguments to ``op`` are the internal numeric values, ie. as returned
 |      by the ``._A`` property.
 |
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
 |      scalar or array then then ``op2`` is invoked
 |
 |      For example::
 |
 |          X._binop(Y, lambda x, y: x + y)
 |
 |      =========   ====  ===================================
 |        Input                    Output
 |      ---------   -----------------------------------------
 |      len(left)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op2(left, right)``
 |       M           M    ``ret[i] = op2(left[i], right)``
 |      =========   ====  ===================================
 |
 |      There is no check on the shape of ``right`` if it is an array.
 |      The result is always a list, except for the first case above and
 |      ``list1`` is ``False``.
 |
 |  extend(self, iterable: 'BasePoseList') -> 'None'
 |      Extend sequence of values in an instance (BasePoseList superclass method)
 |
 |      :param x: the value to extend
 |      :type x: instance of same type
 |      :raises ValueError: incorrect type of appended object
 |
 |      Appends the argument's values to the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.append(X.Alloc(5))   # extend the list
 |          >>> len(x)
 |          15
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
 |      Insert a value to an instance (BasePoseList superclass method)
 |
 |      :param i: element to insert value before
 |      :type i: int
 |      :param item: the value to insert
 |      :type item: instance of same type
 |      :raises ValueError: incorrect type of inserted value
 |
 |      Inserts the argument into the object's internal list of values.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> x.insert(0, X())   # insert at start of list
 |          >>> len(x)
 |          11
 |          >>> x.insert(10, X())   # append to the list
 |          >>> len(x)
 |          11
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |      .. note:: If ``i`` is beyond the end of the list, the item is appended
 |          to the list
 |
 |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
 |      Pop value from an instance (BasePoseList superclass method)
 |
 |      :param i: item in the list to pop, default is last
 |      :type i: int
 |      :return: the popped value
 |      :rtype: instance of same type
 |      :raises IndexError: if there are no values to pop
 |
 |      Removes a value from the value list and returns it.  The original
 |      instance is modified.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |          >>> y = x.pop()  # pop the last value x[9]
 |          >>> len(x)
 |          9
 |          >>> y = x.pop(0)  # pop the first value x[0]
 |          >>> len(x)
 |          8
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
 |      Perform unary operation
 |
 |      :param self: operand
 |      :type self: BasePoseList subclass
 |      :param op: unnary operation
 |      :type op: callable
 |      :param matrix: return array instead of list, default False
 |      :type matrix: bool
 |      :return: operation results
 |      :rtype: list or NumPy array
 |
 |      The is a helper method for implementing unary operations where the
 |      operand has multiple value. This method computes the value of
 |      the operation for all input values and returns the result as either
 |      a list or as a matrix which vertically stacks the results.
 |
 |      =========   ====  ===================================
 |        Input                     Output
 |      ---------   -----------------------------------------
 |      len(self)   len     operation
 |      =========   ====  ===================================
 |       1           1    ``ret = op(self)``
 |       M           M    ``ret[i] = op(self[i])``
 |       M           M    ``ret[i,;] = op(self[i])``
 |      =========   ====  ===================================
 |
 |      The result is:
 |
 |      - a list of values if ``matrix==False``, or
 |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
 |        that the value is a 1D array.
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
 |      Construct an instance with N default values (BasePoseList superclass method)
 |
 |      :param n: Number of values, defaults to 1
 |      :type n: int, optional
 |      :return: pose instance with ``n`` default values
 |
 |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
 |      default values, ie. ``len(X)`` will be ``N``.
 |
 |      ``X`` can be considered a vector of pose objects, and those elements
 |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
 |
 |      .. note:: The default value depends on the pose class and is the result
 |                of the empty constructor. For ``SO2``,
 |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
 |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
 |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
 |                vector.
 |
 |      Example::
 |
 |          >>> x = X.Alloc(10)
 |          >>> len(x)
 |          10
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  Empty() -> 'Self'
 |      Construct an empty instance (BasePoseList superclass method)
 |
 |      :return: pose instance with zero values
 |
 |      Example::
 |
 |          >>> x = X.Empty()
 |          >>> len(x)
 |          0
 |
 |      where ``X`` is any of the SMTB classes.
 |
 |  ----------------------------------------------------------------------
 |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
 |
 |  A
 |      Array value of an instance (BasePoseList superclass method)
 |
 |      :return: NumPy array value of this instance
 |      :rtype: ndarray
 |
 |      - ``X.A`` is a NumPy array that represents the value of this instance,
 |        and has a shape given by ``X.shape``.
 |
 |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
 |          instance.
 |
 |  __array_interface__
 |      Copies the numpy array interface from the first numpy array
 |      so that C extenstions with this spatial math class have direct
 |      access to the underlying numpy array
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.UserList:
 |
 |  __contains__(self, item)
 |
 |  __copy__(self)
 |
 |  __delitem__(self, i)
 |
 |  __iadd__(self, other)
 |
 |  __len__(self)
 |
 |  __radd__(self, other)
 |
 |  clear(self)
 |      S.clear() -> None -- remove all items from S
 |
 |  copy(self)
 |
 |  count(self, item)
 |      S.count(value) -> integer -- return number of occurrences of value
 |
 |  index(self, item, *args)
 |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
 |      Raises ValueError if the value is not present.
 |
 |      Supporting start and stop arguments is optional, but
 |      recommended.
 |
 |  remove(self, item)
 |      S.remove(value) -- remove first occurrence of value.
 |      Raise ValueError if the value is not present.
 |
 |  reverse(self)
 |      S.reverse() -- reverse *IN PLACE*
 |
 |  sort(self, /, *args, **kwds)
 |
 |  ----------------------------------------------------------------------
 |  Data descriptors inherited from collections.UserList:
 |
 |  __dict__
 |      dictionary for instance variables
 |
 |  __weakref__
 |      list of weak references to the object
 |
 |  ----------------------------------------------------------------------
 |  Methods inherited from collections.abc.Sequence:
 |
 |  __iter__(self)
 |
 |  __reversed__(self)
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Reversible:
 |
 |  __subclasshook__(C)
 |      Abstract classes can override this to customize issubclass().
 |
 |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
 |      It should return True, False or NotImplemented.  If it returns
 |      NotImplemented, the normal algorithm is used.  Otherwise, it
 |      overrides the normal algorithm (and the outcome is cached).
 |
 |  ----------------------------------------------------------------------
 |  Class methods inherited from collections.abc.Iterable:
 |
 |  __class_getitem__ = GenericAlias(...)
 |      Represent a PEP 585 generic type
 |
 |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).
spatialmath-python.base
Python Library Documentation: package spatialmath.base in spatialmath

NAME
    spatialmath.base

DESCRIPTION
    # Part of Spatial Math Toolbox for Python
    # Copyright (c) 2000 Peter Corke
    # MIT Licence, see details in top-level file: LICENCE

PACKAGE CONTENTS
    _types_311
    _types_35
    _types_39
    animate
    argcheck
    graphics
    numeric
    quaternions
    symbolic
    transforms2d
    transforms3d
    transformsNd
    types
    vectors

SUBMODULES
    sym

CLASSES
    builtins.object
        spatialmath.base.animate.Animate
        spatialmath.base.animate.Animate2

    class Animate(builtins.object)
     |  Animate(ax: 'Optional[plt.Axes]' = None, dim: 'Optional[ArrayLike]' = None, projection: 'Optional[str]' = 'ortho', labels: 'Optional[Tuple[str, str, str]]' = ('X', 'Y', 'Z'), **kwargs)
     |
     |  Animate objects for matplotlib 3d
     |
     |  An instance of this class behaves like an Axes3D and supports proxies for
     |
     |  - ``plot``
     |  - ``quiver``
     |  - ``text``
     |  - ``scatter``
     |
     |  which renders them and also places corresponding objects into a display
     |  list. These objects are ``Line``, ``Quiver`` and ``Text``.  Only these
     |  primitives will be animated.
     |
     |  The objects are all drawn relative to the origin, and will be transformed
     |  according to the transform that is being animated.
     |
     |  Example::
     |
     |      anim = animate.Animate(dims=[0,2]) # set up the 3D axes
     |      anim.trplot(T, frame='A', color='green')  # draw the frame
     |      anim.run(repeat=True)  # animate it
     |
     |  Methods defined here:
     |
     |  __init__(self, ax: 'Optional[plt.Axes]' = None, dim: 'Optional[ArrayLike]' = None, projection: 'Optional[str]' = 'ortho', labels: 'Optional[Tuple[str, str, str]]' = ('X', 'Y', 'Z'), **kwargs)
     |      Construct an Animate object
     |
     |      :param ax: the axes to plot into, defaults to current axes
     |      :type ax: Axes3D reference
     |      :param dim: dimension of plot volume as [xmin, xmax, ymin, ymax,
     |          zmin, zmax]. If dims is [min, max] those limits are applied
     |          to the x-, y- and z-axes.
     |      :type dim: array_like(6) or array_like(2)
     |      :param projection: 3D projection: ortho [default] or persp
     |      :type projection: str
     |      :param labels: labels for the axes, defaults to X, Y and Z
     |      :type labels: 3-tuple of strings
     |
     |      Will setup to plot into an existing or a new Axes3D instance.
     |
     |  __repr__(self) -> 'str'
     |      Human readable version of the display list
     |
     |      :param self: the animation
     |      :type self: Animate
     |      :returns: readable version of the display list
     |      :rtype: str
     |
     |  __str__(self) -> 'str'
     |      Return str(self).
     |
     |  artists(self) -> 'List[plt.Artist]'
     |      List of artists that need to be updated
     |
     |      :param self: the animation
     |      :type self: Animate
     |      :returns: list of artists
     |      :rtype: list
     |
     |  plot(self, x: 'ArrayLike', y: 'ArrayLike', z: 'ArrayLike', *args: 'List', **kwargs)
     |      Plot a polyline
     |
     |      :param x: list of x-coordinates
     |      :type x: array_like
     |      :param y: list of y-coordinates
     |      :type y: array_like
     |      :param z: list of z-coordinates
     |      :type z: array_like
     |
     |      Other arguments as accepted by the matplotlib method.
     |
     |      All arrays must have the same length.
     |
     |      :seealso: :func:`matplotlib.pyplot.plot`
     |
     |  quiver(self, x: 'ArrayLike', y: 'ArrayLike', z: 'ArrayLike', u: 'ArrayLike', v: 'ArrayLike', w: 'ArrayLike', *args: 'List', **kwargs)
     |      Plot a quiver
     |
     |      :param x: list of base x-coordinates
     |      :type x: array_like
     |      :param y: list of base y-coordinates
     |      :type y: array_like
     |      :param z: list of base z-coordinates
     |      :type z: array_like
     |      :param u: list of vector x-coordinates
     |      :type u: array_like
     |      :param v: list of vector y-coordinates
     |      :type v: array_like
     |      :param w: list of vector z-coordinates
     |      :type w: array_like
     |
     |      Draws a series of arrows, the bases defined by corresponding elements
     |      of (x,y,z) and the vector has components defined by corresponding
     |      elements of (u,v,w).
     |
     |      Other arguments as accepted by the matplotlib method.
     |
     |      :seealso: :func:`matplotlib.pyplot.quiver`
     |
     |  run(self, movie: 'Optional[str]' = None, axes: 'Optional[plt.Axes]' = None, repeat: 'bool' = False, interval: 'int' = 50, nframes: 'int' = 100, wait: 'bool' = False, **kwargs)
     |      Run the animation
     |
     |      :param axes: the axes to plot into, defaults to current axes
     |      :type axes: Axes3D reference
     |      :param repeat: animate in endless loop [default False]
     |      :type repeat: bool
     |      :param nframes: number of steps in the animation [default 100]
     |      :type nframes: int
     |      :param interval: number of milliseconds between frames [default 50]
     |      :type interval: int
     |      :param movie: name of file to write MP4 movie into, or True
     |      :type movie: str, bool
     |      :param wait: wait until animation is complete, default False
     |      :type wait: bool
     |
     |      Animates a 3D coordinate frame moving from the world frame to a frame
     |      represented by the SO(3) or SE(3) matrix to the current axes.
     |
     |      .. note::
     |
     |          - the ``movie`` option requires the ffmpeg package to be installed:
     |            ``conda install -c conda-forge ffmpeg``
     |          - if ``movie=True`` then return an HTML5 video which can be displayed in a notebook
     |            using ``HTML()``
     |          - invokes the draw() method of every object in the display list
     |
     |  scatter(self, xs: 'ArrayLike', ys: 'ArrayLike', zs: 'ArrayLike', s: 'float' = 0, **kwargs)
     |
     |  set_proj_type(self, proj_type: 'str')
     |
     |  set_xlabel(self, *args: 'List', **kwargs)
     |
     |  set_xlim(self, *args: 'List', **kwargs)
     |
     |  set_ylabel(self, *args: 'List', **kwargs)
     |
     |  set_ylim(self, *args: 'List', **kwargs)
     |
     |  set_zlabel(self, *args: 'List', **kwargs)
     |
     |  set_zlim(self, *args: 'List', **kwargs)
     |
     |  text(self, x: 'float', y: 'float', z: 'float', *args: 'List', **kwargs)
     |      Plot text
     |
     |      :param x: x-coordinate
     |      :type x: float
     |      :param y: float
     |      :type y: float
     |      :param z: z-coordinate
     |      :type z: float
     |      :param kwargs: Other arguments as accepted by the matplotlib method.
     |
     |      ``.text(x, y, z, s)`` display the string ``s`` at coordinate
     |      (``x``, ``y``, ``z``).
     |
     |      :seealso: :func:`~matplotlib.pyplot.text`
     |
     |  trplot(self, end: 'Union[SO3Array, SE3Array]', start: 'Optional[Union[SO3Array, SE3Array]]' = None, **kwargs)
     |      Define the transform to animate
     |
     |      :param end: the final pose SE(3) or SO(3) to display as a coordinate frame
     |      :type end: ndarray(4,4) or ndarray(3,3)
     |      :param start: the initial pose SE(3) or SO(3) to display as a coordinate frame, defaults to null
     |      :type start: ndarray(4,4) or ndarray(3,3)
     |      :param start: an
     |
     |      Is polymorphic with ``base.trplot`` and accepts the same parameters.
     |      This sets up the animation but doesn't execute it.
     |
     |      :seealso: :func:`run`
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class Animate2(builtins.object)
     |  Animate2(axes: 'Optional[plt.Axes]' = None, dims: 'Optional[ArrayLike]' = None, labels: 'Tuple[str, str]' = ('X', 'Y'), **kwargs)
     |
     |  Animate objects for matplotlib 2d
     |
     |  An instance of this class behaves like an Axes3D and supports proxies for
     |
     |  - ``plot``
     |  - ``quiver``
     |  - ``text``
     |
     |  which renders them and also places corresponding objects into a display
     |  list. These objects are ``Line``, ``Quiver`` and ``Text``.  Only these
     |  primitives will be animated.
     |
     |  The objects are all drawn relative to the origin, and will be transformed
     |  according to the transform that is being animated.
     |
     |  Example::
     |
     |      anim = animate.Animate(dims=[0,2]) # set up the 3D axes
     |      anim.trplot(T, frame='A', color='green')  # draw the frame
     |      anim.run(loop=True)  # animate it
     |
     |  Methods defined here:
     |
     |  __init__(self, axes: 'Optional[plt.Axes]' = None, dims: 'Optional[ArrayLike]' = None, labels: 'Tuple[str, str]' = ('X', 'Y'), **kwargs)
     |      Construct an Animate object
     |
     |      :param axes: the axes to plot into, defaults to current axes
     |      :type axes: Axes3D reference
     |      :param dims: dimension of plot volume as [xmin, xmax, ymin, ymax]. If
     |          dims is [min, max] those limits are applied to the x- and y-axes.
     |      :type dims: array_like(4) or array_like(2)
     |      :param projection: 3D projection: ortho [default] or persp
     |      :type projection: str
     |      :param labels: labels for the axes, defaults to X, Y and Z
     |      :type labels: 3-tuple of strings
     |
     |      Will setup to plot into an existing or a new Axes3D instance.
     |
     |  __repr__(self)
     |      Human readable version of the display list
     |
     |      :param self: the animation
     |      :type self: Animate
     |      :returns: readable version of the display list
     |      :rtype: str
     |
     |  __str__(self)
     |      Return str(self).
     |
     |  artists(self)
     |      List of artists that need to be updated
     |
     |      :param self: the animation
     |      :type self: Animate
     |      :returns: list of artists
     |      :rtype: list
     |
     |  autoscale(self, *args, **kwargs)
     |
     |  plot(self, x, y, *args, **kwargs)
     |      Plot a polyline
     |
     |      :param x: list of x-coordinates
     |      :type x: array_like
     |      :param y: list of y-coordinates
     |      :type y: array_like
     |
     |      Other arguments as accepted by the matplotlib method.
     |
     |      All arrays must have the same length.
     |
     |      :seealso: :func:`matplotlib.pyplot.plot`
     |
     |  quiver(self, x, y, u, v, *args, **kwargs)
     |      Plot a quiver
     |
     |      :param x: list of base x-coordinates
     |      :type x: array_like
     |      :param y: list of base y-coordinates
     |      :type y: array_like
     |      :param u: list of vector x-coordinates
     |      :type u: array_like
     |      :param v: list of vector y-coordinates
     |      :type v: array_like
     |
     |
     |      Draws a series of arrows, the bases defined by corresponding elements
     |      of (x,y,z) and the vector has components defined by corresponding
     |      elements of (u,v,w).
     |
     |      Other arguments as accepted by the matplotlib method.
     |
     |      :seealso: :func:`matplotlib.pyplot.quiver`
     |
     |  run(self, movie: 'Optional[str]' = None, axes: 'Optional[plt.Axes]' = None, repeat: 'bool' = False, interval: 'int' = 50, nframes: 'int' = 100, wait: 'bool' = False, **kwargs)
     |      Run the animation
     |
     |      :param axes: the axes to plot into, defaults to current axes
     |      :type axes: Axes reference
     |      :param nframes: number of steps in the animation [defaault 100]
     |      :type nframes: int
     |      :param repeat: animate in endless loop [default False]
     |      :type repeat: bool
     |      :param interval: number of milliseconds between frames [default 50]
     |      :type interval: int
     |      :param movie: name of file to write MP4 movie into or True
     |      :type movie: str, bool
     |      :returns: Matplotlib animation object
     |      :rtype: Matplotlib animation object
     |
     |      Animates a 3D coordinate frame moving from the world frame to a frame
     |      represented by the SO(2) or SE(2) matrix to the current axes.
     |
     |      .. note::
     |
     |          - the ``movie`` option requires the ffmpeg package to be installed:
     |            ``conda install -c conda-forge ffmpeg``
     |          - if ``movie=True`` then return an HTML5 video which can be displayed in a notebook
     |            using ``HTML()``
     |          - invokes the draw() method of every object in the display list
     |
     |  scatter(self, x, y, s=0, **kwargs)
     |
     |  set_aspect(self, *args, **kwargs)
     |
     |  set_xlabel(self, *args, **kwargs)
     |
     |  set_xlim(self, *args, **kwargs)
     |
     |  set_ylabel(self, *args, **kwargs)
     |
     |  set_ylim(self, *args, **kwargs)
     |
     |  text(self, x, y, *args, **kwargs)
     |      Plot text
     |
     |      :param x: x-coordinate
     |      :type x: float
     |      :param y: float
     |      :type y: float
     |      :param z: z-coordinate
     |      :type z: float
     |      :param kwargs: Other arguments as accepted by the matplotlib method.
     |
     |      ``.text(x, y, s)`` display the string ``s`` at coordinate
     |      (``x``, ``y``).
     |
     |      :seealso: :func:`matplotlib.pyplot.text`
     |
     |  trplot2(self, end: 'Union[SO2Array, SE2Array]', start: 'Optional[Union[SO2Array, SE2Array]]' = None, **kwargs)
     |      Define the transform to animate
     |
     |      :param end: the final pose SE(2) or SO(2) to display as a coordinate frame
     |      :type end: ndarray(3,3) or ndarray(2,2)
     |      :param start: the initial pose SE(2) or SO(2) to display as a coordinate frame, defaults to null
     |      :type start: ndarray(3,3) or ndarray(2,2)
     |
     |      Is polymorphic with ``base.trplot`` and accepts the same parameters.
     |      This sets up the animation but doesn't execute it.
     |
     |      :seealso: :func:`run`
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

FUNCTIONS
    Ab2M(A: numpy.ndarray, b: numpy.ndarray) -> numpy.ndarray
        Pack matrix and vector to matrix

        :param A: square matrix
        :type A: ndarray(3,3) or ndarray(2,2)
        :param b: translation vector
        :type b: ndarray(3) or ndarray(2)
        :return: matrix
        :rtype: ndarray(4,4) or ndarray(3,3)
        :raises ValueError: bad arguments

        ``M = Ab2M(A, b)`` is a matrix (N+1xN+1) formed from a matrix ``R`` (NxN) and a vector ``t``
        (Nx1).  The bottom row is all zeros.

        - If ``A`` is 2x2 and ``b`` is 2x1, then ``M`` is 3x3
        - If ``A`` is 3x3 and ``b`` is 3x1, then ``M`` is 4x4

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> A = np.c_[[1, 2], [3, 4]].T
            >>> b = [5, 6]
            >>> Ab2M(A, b)

        :seealso: rt2tr, tr2rt, r2t

    angdiff(a, b=None)
        Angular difference

        :param a: angle in radians
        :type a: scalar or array_like
        :param b: angle in radians
        :type b: scalar or array_like
        :return: angular difference a-b
        :rtype: scalar or array_like

        - ``angdiff(a, b)`` is the difference ``a - b`` wrapped to the range
          :math:`[-\pi, \pi)`.  This is the operator :math:`a \circleddash b` used
          in the RVC book

            - If ``a`` and ``b`` are both scalars, the result is scalar
            - If ``a`` is array_like, the result is a NumPy array ``a[i]-b``
            - If ``a`` is array_like, the result is a NumPy array ``a-b[i]``
            - If ``a`` and ``b`` are both vectors of the same length, the result is
              a NumPy array ``a[i]-b[i]``

        - ``angdiff(a)`` is the angle or vector of angles ``a`` wrapped to the range
          :math:`[-\pi, \pi)`.

            - If ``a`` is a scalar, the result is scalar
            - If ``a`` is array_like, the result is a NumPy array

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> from math import pi
            >>> angdiff(0, 2 * pi)
            >>> angdiff(0.9 * pi, -0.9 * pi) / pi
            >>> angdiff(3 * pi)

        :seealso: :func:`vector_diff` :func:`wrap_mpi_pi`

    angvec2r(theta: float, v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], unit='rad', tol: float = 20) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create an SO(3) rotation matrix from rotation angle and axis

        :param theta: rotation
        :type theta: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :param v: 3D rotation axis
        :type v: array_like(3)
        :param tol: Tolerance in units of eps for zero-rotation case, defaults to 20
        :type: float
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)
        :raises ValueError: bad arguments

        ``angvec2r(θ, V)`` is an SO(3) orthonormal rotation matrix
        equivalent to a rotation of ``θ`` about the vector ``V``.

        .. runblock:: pycon

            >>> from spatialmath.base import angvec2r
            >>> angvec2r(0.3, [1, 0, 0])  # rotx(0.3)
            >>> angvec2r(0, [1, 0, 0])    # rotx(0)

        .. note::

            - If ``θ == 0`` then return identity matrix.
            - If ``θ ~= 0`` then ``V`` must have a finite length.

        :seealso: :func:`~angvec2tr` :func:`~tr2angvec`

        :SymPy: not supported

    angvec2tr(theta: float, v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], unit='rad') -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create an SE(3) pure rotation from rotation angle and axis

        :param theta: rotation
        :type theta: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :param v: 3D rotation axis
        :type v: : array_like(3)
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        ``angvec2tr(θ, V)`` is an SE(3) homogeneous transformation matrix
        equivalent to a rotation of ``θ`` about the vector ``V``.

        .. runblock:: pycon

            >>> from spatialmath.base import angvec2tr
            >>> angvec2tr(0.3, [1, 0, 0])  # rtotx(0.3)

        .. note::

            - If ``θ == 0`` then return identity matrix.
            - If ``θ ~= 0`` then ``V`` must have a finite length.
            - The translational part is zero.

        :seealso: :func:`~angvec2r` :func:`~tr2angvec`

        :SymPy: not supported

    angvelxform(Γ, inverse=False, full=True, representation='rpy/xyz')
        DEPRECATED, use :func:`rotvelxform` instead

    angvelxform_dot(Γ, Γd, full=True, representation='rpy/xyz')
        DEPRECATED, use :func:`rotvelxform` instead

    array2str(X: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], valuesep: str = ', ', rowsep: str = ' | ', fmt: str = '{:.3g}', brackets: Tuple[str, str] = ('[ ', ' ]'), suppress_small: bool = True) -> str
        Convert array to single line string

        :param X: 1D or 2D array to convert
        :type X: ndarray(N,M), array_like(N)
        :param valuesep: separator between numbers, defaults to ", "
        :type valuesep: str, optional
        :param rowsep: separator between rows, defaults to " | "
        :type rowsep: str, optional
        :param format: format string, defaults to "{:.3g}"
        :type precision: str, optional
        :param brackets: strings to be added to start and end of the string,
            defaults to ("[ ", " ]").  Set to None to suppress brackets.
        :type brackets: list, tuple of str
        :param suppress_small: small values (:math:`|x| < 10^{-12}` are converted
            to zero, defaults to True
        :type suppress_small: bool, optional
        :return: compact string representation of array
        :rtype: str

        Converts a small array to a compact single line representation.

        Example:

        .. runblock:: pycon

            >>> from spatialmath.base import array2str
            >>> import numpy as np
            >>> array2str(np.random.rand(2,2))
            >>> array2str(np.random.rand(2,2), rowsep="; ")  # MATLAB-like
            >>> array2str(np.random.rand(3,))
            >>> array2str(np.random.rand(3,1))


        :seealso: :func:`array2str`

    assertmatrix(m: Any, shape: Tuple[Optional[int], Optional[int]] = (None, None)) -> None
        Assert that argument is a 2D matrix

        :param m: value to test
        :param shape: required shape
        :type shape: 2-tuple
        :raises TypeError: if value is not a real Numpy array
        :raises ValueError: if value is not of the specified shape

        Tests if the argument is a real 2D matrix with a specified shape ``shape``
        but the value ``None`` indicate an unspecified (wildcard, don't care)
        dimension.

        - ``assertsmatrix(A)`` raises an exception if ``m`` is not convertible to
          a 2D array
        - ``assertsmatrix(A, (N,M))`` as above but ``m`` must have shape
          (``N``,``M``)
        - ``assertsmatrix(A, (N,None))`` as above but ``m`` must have ``N`` rows
        - ``assertsmatrix(A, (None,M))`` as above but ``m`` must have ``M`` columns

        :seealso: :func:`ismatrix`

    assertvector(v: Any, dim: Optional[int] = None, msg: Optional[str] = None) -> None
        Assert that argument is a real vector

        :param v: passed vector
        :param dim: required dimension
        :type dim: int or None
        :raises ValueError: if not a vector of specified length

        - ``assertvector(vec)`` raise an exception if ``vec`` is not a vector, ie.
          it is not any of:

            - a Python native int or float, a 1-vector
            - Python native list or tuple
            - numPy real 1D array, ie. shape=(N,)
            - numPy real 2D array with a singleton dimension, ie. shape=(1,N)
              or (N,1)

        - ``assertvector(vec, N)`` as above but must also check the length is ``N``.

        :seealso: :func:`getvector`, :func:`isvector`

    axes_logic(ax: Union[matplotlib.axes._axes.Axes, mpl_toolkits.mplot3d.axes3d.Axes3D, NoneType], dimensions: int, projection: Optional[str] = 'ortho', autoscale: Optional[bool] = True, new: Optional[bool] = False) -> Union[matplotlib.axes._axes.Axes, mpl_toolkits.mplot3d.axes3d.Axes3D]
        Axis creation logic

        :param ax: axes to draw in
        :type ax: Axes3DSubplot, AxesSubplot or None
        :param dimensions: required dimensionality, 2 or 3
        :type dimensions: int
        :param projection: 3D projection type, defaults to 'ortho'
        :type projection: str, optional
        :param new: create a new figure, defaults to False
        :type new: bool
        :return: axes to draw in
        :rtype: Axes3DSubplot or AxesSubplot

        Given a request for axes with either 2 or 3 dimensions it checks for a
        match with the passed axes ``ax`` or the current axes.

        If the dimensions do not match, or no figure/axes currently exist,
        then ``plt.axes()`` is called to create one.

        If ``new`` is True then a new 3D axes is created regardless of whether the
        current axis is 3D.

        Used by all plot_xxx() functions in this module.

    bresenham(p0: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], p1: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]]) -> Tuple[numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Line drawing in a grid

        :param p0: initial point
        :type p0: array_like(2) of int
        :param p1: end point
        :type p1: array_like(2) of int
        :return: arrays of x and y coordinates for points along the line
        :rtype: ndarray(N), ndarray(N) of int

        Return x and y coordinate vectors for points in a grid that lie on
        a line from ``p0`` to ``p1`` inclusive.

        * The end points, and all points along the line are integers.
        * Points are always adjacent, but the slope from point to point is not constant.


        Example:

        .. runblock:: pycon

            >>> from spatialmath.base import bresenham
            >>> bresenham((2, 4), (10, 10))

        .. plot::

            from spatialmath.base import bresenham
            import matplotlib.pyplot as plt
            p = bresenham((2, 4), (10, 10))
            plt.plot((2, 10), (4, 10))
            plt.plot(p[0], p[1], 'ok')
            plt.plot(p[0], p[1], 'k', drawstyle='steps-post')
            ax = plt.gca()
            ax.grid()


        .. note:: The API is similar to the Bresenham algorithm but this
            implementation uses NumPy vectorised arithmetic which makes it
            faster than the Bresenham algorithm in Python.

    circle(centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]] = (0, 0), radius: float = 1, resolution: int = 50, closed: bool = False) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Points on a circle

        :param centre: centre of circle, defaults to (0, 0)
        :type centre: array_like(2), optional
        :param radius: radius of circle, defaults to 1
        :type radius: float, optional
        :param resolution: number of points on circumferece, defaults to 50
        :type resolution: int, optional
        :param closed: perimeter is closed, last point == first point, defaults to False
        :type closed: bool
        :return: points on circumference
        :rtype: ndarray(2,N) or ndarray(3,N)

        Returns a set of ``resolution`` that lie on the circumference of a circle
        of given ``center`` and ``radius``.

        If ``len(centre)==3`` then the 3D coordinates are returned, where the
        circle lies in the xy-plane and the z-coordinate comes from ``centre[2]``.

        .. note:: By default returns a unit circle centred at the origin.

    colvec(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Create a column vector

        :param v: any vector
        :type v: array_like(n)
        :return: a column vector
        :rtype: ndarray(n,1)

        Convert input to a column vector.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> colvec([1, 2, 3])

    cross(u: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Cross product of vectors

        :param u: any vector
        :type u: array_like(3)
        :param v: any vector
        :type v: array_like(3)
        :return: cross product
        :rtype: nd.array(3)

        ``cross(u, v)`` is the cross product of the vectors ``u`` and ``v``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> cross([1, 0, 0], [0, 1, 0])

        .. note:: This function does not use NumPy, it is ~1.5x faster than
            `numpy.cross()`

        :seealso: :func:`~spatialmath.base.unit`

        :SymPy: supported

    delta2tr(d: numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Convert differential motion to SE(3)

        :param Δ: differential motion as a 6-vector
        :type Δ: array_like(6)
        :return: SE(3) matrix
        :rtype: ndarray(4,4)

        ``delta2tr(Δ)`` is an SE(3) matrix representing differential
        motion :math:`\Delta = [\delta_x, \delta_y, \delta_z, \theta_x, \theta_y, \theta_z]`.

        .. runblock:: pycon

            >>> from spatialmath.base import delta2tr
            >>> delta2tr([0.001, 0, 0, 0, 0.002, 0])

        :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.

        :seealso: :func:`~tr2delta`
        :SymPy: supported

    e2h(v: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Convert from Euclidean to homogeneous form

        :param v: Euclidean vector or matrix
        :type v: array_like(n), ndarray(n,m)
        :return: homogeneous vector
        :rtype: ndarray(n+1,m)

        - If ``v`` is an N-vector, return an (N+1)-column vector where a value of 1 has
          been appended as the last element.
        - If ``v`` is a matrix (NxM), return a matrix (N+1xM), where each column has
          been appended with a value of 1, ie. a row of ones has been appended to the matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> e2h([2, 4, 6])
            >>> e = np.c_[[1,2], [3,4], [5,6]]
            >>> e
            >>> e2h(e)

        .. note:: The result is always a 2D array, a 1D input results in a column vector.

        :seealso: e2h

    ellipse(E: numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]], numpy.dtype[numpy.floating]], centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = (0, 0), scale: Optional[float] = 1, confidence: Optional[float] = None, resolution: Optional[int] = 40, inverted: Optional[bool] = False, closed: Optional[bool] = False) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Points on ellipse

        :param E: ellipse
        :type E: ndarray(2,2)
        :param centre: ellipse centre, defaults to (0,0,0)
        :type centre: tuple, optional
        :param scale: scale factor for the ellipse radii
        :type scale: float
        :param confidence: if E is an inverse covariance matrix plot an ellipse
            for this confidence interval in the range [0,1], defaults to None
        :type confidence: float, optional
        :param resolution: number of points on circumferance, defaults to 40
        :type resolution: int, optional
        :param inverted: if :math:`\mat{E}^{-1}` is provided, defaults to False
        :type inverted: bool, optional
        :param closed: perimeter is closed, last point == first point, defaults to False
        :type closed: bool
        :raises ValueError: [description]
        :return: points on circumference
        :rtype: ndarray(2,N)

        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
            - for robot manipulability
            :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``.

    ellipsoid(E: numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]], numpy.dtype[numpy.floating]], centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), scale: Optional[float] = 1, confidence: Optional[float] = None, resolution: Optional[int] = 40, inverted: Optional[bool] = False) -> Tuple[numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Points on an ellipsoid

        :param centre: centre of ellipsoid, defaults to (0, 0, 0)
        :type centre: array_like(3), optional
        :param scale: scale factor for the ellipse radii
        :type scale: float
        :param confidence: confidence interval, range 0 to 1
        :type confidence: float
        :param resolution: number of points ``N`` on circumferece, defaults to 40
        :type resolution: int, optional
        :param inverted: :math:`E^{-1}` rather than :math:`E` provided, defaults to False
        :type inverted: bool, optional
        :return: X, Y and Z braid matrices
        :rtype: 3 x ndarray(N, N)

        The ellipse is defined by :math:`x^T \mat{E} x = s^2` where :math:`x \in
        \mathbb{R}^3` and :math:`s` is the scale factor.

        .. 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
            - 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``.

        :seealso: :func:`plot_ellipsoid`, :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    eul2jac(angles: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Euler angle rate Jacobian

        :param angles: Euler angles (φ, θ, ψ)
        :type angles: array_like(3)
        :return: Jacobian matrix
        :rtype: ndarray(3,3)

        - ``eul2jac(φ, θ, ψ)`` is a Jacobian matrix (3x3) that maps ZYZ Euler angle
          rates to angular velocity at the operating point specified by the Euler
          angles φ, ϴ, ψ.
        - ``eul2jac(𝚪)`` as above but the Euler angles are taken from ``𝚪`` which
          is a 3-vector with values (φ θ ψ).

        Example:

        .. runblock:: pycon

            >>> from spatialmath.base import eul2jac
            >>> eul2jac([0.1, 0.2, 0.3])

        .. note::
            - Used in the creation of an analytical Jacobian.
            - Angles in radians, rates in radians/sec.

        :Reference: Robotics, Vision & Control for Python, Section 8.1.3, P. Corke, Springer 2023.

        :SymPy: supported

        :seealso: :func:`angvelxform` :func:`rpy2jac` :func:`exp2jac`

    eul2r(phi: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], float], theta: Optional[float] = None, psi: Optional[float] = None, unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create an SO(3) rotation matrix from Euler angles

        :param phi: Z-axis rotation
        :type phi: float
        :param theta: Y-axis rotation
        :type theta: float
        :param psi: Z-axis rotation
        :type psi: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        - ``R = eul2r(φ, θ, ψ)`` is an SO(3) orthonornal rotation
          matrix equivalent to the specified Euler angles.  These correspond
          to rotations about the Z, Y, Z axes respectively.
        - ``R = eul2r(EUL)`` as above but the Euler angles are taken from
          ``EUL`` which is a 3-vector with values (φ θ ψ).

        .. runblock:: pycon

            >>> from spatialmath.base import eul2r
            >>> eul2r(0.1, 0.2, 0.3)
            >>> eul2r([0.1, 0.2, 0.3])
            >>> eul2r([10, 20, 30], unit='deg')

        :seealso: :func:`~rpy2r` :func:`~eul2tr` :func:`~tr2eul`

        :SymPy: supported

    eul2tr(phi, theta=None, psi=None, unit='rad') -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create an SE(3) pure rotation matrix from Euler angles

        :param phi: Z-axis rotation
        :type phi: float
        :param theta: Y-axis rotation
        :type theta: float
        :param psi: Z-axis rotation
        :type psi: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        - ``R = eul2tr(PHI, θ, PSI)`` is an SE(3) homogeneous transformation
          matrix equivalent to the specified Euler angles.  These correspond
          to rotations about the Z, Y, Z axes respectively.
        - ``R = eul2tr(EUL)`` as above but the Euler angles are taken from
          ``EUL`` which is a 3-vector with values
          (PHI θ PSI).


        .. runblock:: pycon

            >>> from spatialmath.base import eul2tr
            >>> eul2tr(0.1, 0.2, 0.3)
            >>> eul2tr([0.1, 0.2, 0.3])
            >>> eul2tr([10, 20, 30], unit='deg')

        .. note:: By default, the translational component is zero but it can be
            set to a non-zero value.

        :seealso: :func:`~rpy2tr` :func:`~eul2r` :func:`~tr2eul`

        :SymPy: supported

    exp2jac(v: numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Jacobian from exponential coordinate rates to angular velocity

        :param v: Exponential coordinates
        :type v: array_like(3)
        :return: Jacobian matrix
        :rtype: ndarray(3,3)

        - ``exp2jac(v)`` is a Jacobian matrix (3x3) that maps exponential coordinate
          rates to angular velocity at the operating point ``v``.

        .. runblock:: pycon

            >>> from spatialmath.base import exp2jac
            >>> exp2jac([0.3, 0, 0])

        .. note::
            - Used in the creation of an analytical Jacobian.

        Reference::

            - A compact formula for the derivative of a 3-D rotation in
              exponential coordinate
              Guillermo Gallego, Anthony Yezzi
              https://arxiv.org/pdf/1312.0788v1.pdf
            - Robot Dynamics Lecture Notes
              Robotic Systems Lab, ETH Zurich, 2018
              https://ethz.ch/content/dam/ethz/special-interest/mavt/robotics-n-intelligent-systems/rsl-dam/documents/RobotDynamics2018/RD_HS2018script.pdf

        :SymPy: supported

        :seealso: :func:`rotvelxform` :func:`eul2jac` :func:`rpy2jac`

    exp2r(w: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create an SO(3) rotation matrix from exponential coordinates

        :param w: exponential coordinate vector
        :type w: array_like(3)
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)
        :raises ValueError: bad arguments

        ``exp2r(w)`` is an SO(3) orthonormal rotation matrix
        equivalent to a rotation of :math:`\| w \|` about the vector :math:`\hat{w}`.

        If ``w`` is zero then result is the identity matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import exp2r, rotx
            >>> exp2r([0.3, 0, 0])
            >>> rotx(0.3)

        .. note:: Exponential coordinates are also known as an Euler vector

        :seealso: :func:`~angvec2r` :func:`~tr2angvec`

        :SymPy: not supported

    exp2tr(w: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create an SE(3) pure rotation matrix from exponential coordinates

        :param w: exponential coordinate vector
        :type w: array_like(3)
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)
        :raises ValueError: bad arguments

        ``exp2r(w)`` is an SO(3) orthonormal rotation matrix
        equivalent to a rotation of :math:`\| w \|` about the vector :math:`\hat{w}`.

        If ``w`` is zero then result is the identity matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import exp2tr, trotx
            >>> exp2tr([0.3, 0, 0])
            >>> trotx(0.3)

        .. note:: Exponential coordinates are also known as an Euler vector

        :seealso: :func:`~angvec2r` :func:`~tr2angvec`

        :SymPy: not supported

    expand_dims(dim: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]] = None, nd: int = 2) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Expand compact axis dimensions

        :param dim: dimensions, defaults to None
        :type dim: scalar, array_like(2), array_like(4), array_like(6), optional
        :param nd: number of axes dimensions, defaults to 2
        :type nd: int, optional
        :raises ValueError: bad arguments
        :return: 2d or 3d dimensions vector
        :rtype: ndarray(4) or ndarray(6)

        Compute bounding dimensions for plots from shorthand notation.

        If ``nd==2``, [xmin, xmax, ymin, ymax]:
            * A -> [-A, A, -A, A]
            * [A,B] -> [A, B, A, B]
            * [A,B,C,D] -> [A, B, C, D]

        If ``nd==3``, [xmin, xmax, ymin, ymax, zmin, zmax]:
            * A -> [-A, A, -A, A, -A, A]
            * [A,B] -> [A, B, A, B, A, B]
            * [A,B,C,D,E,F] -> [A, B, C, D, E, F]

    gauss1d(mu: float, var: float, x: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]])
        Gaussian function in 1D

        :param mu: mean
        :type mu: float
        :param var: variance
        :type var: float
        :param x: x-coordinate values
        :type x: array_like(n)
        :return: Gaussian :math:`G(x)`
        :rtype: ndarray(n)

        Example::

            >>> g = gauss1d(5, 2, np.linspace(0, 10, 100))

        .. plot::

            from spatialmath.base import gauss1d
            import matplotlib.pyplot as plt
            import numpy as np
            x = np.linspace(0, 10, 100)
            g = gauss1d(5, 2, x)
            plt.plot(x, g)
            plt.grid()

        :seealso: :func:`gauss2d`

    gauss2d(mu: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], P: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], X: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], Y: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Gaussian function in 2D

        :param mu: mean
        :type mu: array_like(2)
        :param P: covariance matrix
        :type P: ndarray(2,2)
        :param X: array of x-coordinates
        :type X:  ndarray(n,m)
        :param Y: array of y-coordinates
        :type Y: ndarray(n,m)
        :return: Gaussian :math:`g(x,y)`
        :rtype: ndarray(n,m)

        Computed :math:`g_{i,j} = G(x_{i,j}, y_{i,j})`

        Example (RVC3 Fig G.2)::

            >>> a = np.linspace(-5, 5, 100)
            >>> X, Y = np.meshgrid(a, a)
            >>> P = np.diag([1, 2])**2;
            >>> g = gauss2d(X, Y, [0, 0], P)

        .. plot::

            from spatialmath.base import gauss2d, plotvol3
            import matplotlib.pyplot as plt
            import numpy as np
            a = np.linspace(-5, 5, 100)
            x, y = np.meshgrid(a, a)
            P = np.diag([1, 2])**2;
            g = gauss2d([0, 0], P, x, y)
            ax = plotvol3()
            ax.plot_surface(x, y, g)

        :seealso: :func:`gauss1d`

    getunit(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], unit: str = 'rad', dim: Optional[int] = None, vector: bool = True) -> Union[float, numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Convert values according to angular units

        :param v: the value in radians or degrees
        :type v: array_like(m)
        :param unit: the angular unit, "rad" or "deg"
        :type unit: str
        :param dim: expected dimension of input, defaults to don't check (None)
        :type dim: int, optional
        :param vector: return a scalar as a 1d vector, defaults to True
        :type vector: bool, optional
        :return: the converted value in radians
        :rtype: ndarray(m) or float
        :raises ValueError: argument is not a valid angular unit

        The input value is assumed to be in units of ``unit`` and is converted to radians.

        .. runblock:: pycon

            >>> from spatialmath.base import getunit
            >>> import numpy as np
            >>> getunit(1.5, 'rad')
            >>> getunit(90, 'deg')
            >>> getunit(90, 'deg', vector=False) # force a scalar output
            >>> getunit(1.5, 'rad', dim=0) # check argument is scalar
            >>> getunit(1.5, 'rad', dim=3) # check argument is a 3-vector
            >>> getunit([1.5], 'rad', dim=1) # check argument is a 1-vector
            >>> getunit([1.5], 'rad', dim=3) # check argument is a 3-vector
            >>> getunit([90, 180], 'deg')
            >>> getunit(np.r_[90, 180], 'deg')
            >>> getunit(np.r_[90, 180], 'deg', dim=2) # check argument is a 2-vector
            >>> getunit([90, 180], 'deg', dim=3) # check argument is a 3-vector

        :note:
            - the input value is processed by :func:`getvector` and the argument ``dim`` can
              be used to check that ``v`` is the desired length.  Note that 0 means a scalar,
              whereas 1 means a 1-element array.
            - the output is always an ndarray except if the input is a scalar and ``vector=False``.

        :seealso: :func:`getvector`

    getvector(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], dim: Optional[int] = None, out: str = 'array', dtype: Union[numpy.dtype[Any], NoneType, type[Any], numpy._typing._dtype_like._SupportsDType[numpy.dtype[Any]], str, tuple[Any, int], tuple[Any, SupportsIndex | collections.abc.Sequence[SupportsIndex]], list[Any], numpy._typing._dtype_like._DTypeDict, tuple[Any, Any]] = <class 'numpy.float64'>) -> Union[numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], List[float], Tuple[float, ...]]
        Return a vector value

        :param v: passed vector
        :param dim: required dimension, or None if any length is ok
        :type dim: int or None
        :param out: output format, default is 'array'
        :type out: str
        :param dtype: datatype for numPy array return (default np.float64)
        :type dtype: numPy type
        :return: vector value in specified format
        :raises TypeError: value is not a list or NumPy array
        :raises ValueError: incorrect number of elements

        - ``getvector(vec)`` is ``vec`` converted to the output format ``out``
          where ``vec`` is any of:

            - a Python native int or float, a 1-vector
            - Python native list or tuple
            - numPy real 1D array, ie. shape=(N,)
            - numPy real 2D array with a singleton dimension, ie. shape=(1,N)
              or (N,1)

        - ``getvector(vec, N)`` as above but must be an ``N``-element vector.

        The returned vector will be in the format specified by ``out``:

        ==========  ===============================================
        format      return type
        ==========  ===============================================
        'sequence'  Python list, or tuple if a tuple was passed in
        'list'      Python list
        'array'     1D numPy array, shape=(N,)  [default]
        'row'       row vector, a 2D numPy array, shape=(1,N)
        'col'       column vector, 2D numPy array, shape=(N,1)
        ==========  ===============================================

        .. runblock:: pycon

            >>> from spatialmath.base import getvector
            >>> import numpy as np
            >>> getvector([1,2])  # list
            >>> getvector([1,2], out='row')  # list
            >>> getvector([1,2], out='col')  # list
            >>> getvector((1,2))  # tuple
            >>> getvector(np.r_[1,2,3], out='sequence')  # numpy array
            >>> getvector(1)  # scalar
            >>> getvector([1])
            >>> getvector([[1]])
            >>> getvector([1,2], 2)
            >>> # getvector([1,2], 3)  --> ValueError

        .. note::
            - For 'array', 'row' or 'col' output the NumPy dtype defaults to the
              ``dtype`` of ``v`` if it is a NumPy array, otherwise it is
              set to the value specified by the ``dtype`` keyword which defaults
              to ``np.float64``.
            - If ``v`` is symbolic the ``dtype`` is retained as ``'O'``

        :seealso: :func:`isvector`

    h2e(v: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Convert from homogeneous to Euclidean form

        :param v: homogeneous vector or matrix
        :type v: array_like(n), ndarray(n,m)
        :return: Euclidean vector
        :rtype: ndarray(n-1), ndarray(n-1,m)

        - If ``v`` is an N-vector, return an (N-1)-column vector where the elements have
          all been scaled by the last element of ``v``.
        - If ``v`` is a matrix (NxM), return a matrix (N-1xM), where each column has
          been scaled by its last element.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> h2e([2, 4, 6, 1])
            >>> h2e([2, 4, 6, 2])
            >>> h = np.c_[[1,2,1], [3,4,2], [5,6,1]]
            >>> h
            >>> h2e(h)

        .. note:: The result is always a 2D array, a 1D input results in a column vector.

        :seealso: e2h

    homtrans(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], p: numpy.ndarray) -> numpy.ndarray
        Apply a homogeneous transformation to a Euclidean vector

        :param T: homogeneous transformation
        :type T: Numpy array (n,n)
        :param p: Vector(s) to be transformed
        :type p: array_like(n-1), ndarray(n-1,m)
        :return: transformed Euclidean vector(s)
        :rtype: ndarray(n-1,m)
        :raises ValueError: bad argument

        - ``homtrans(T, p)`` applies the homogeneous transformation ``T`` to the Euclidean points
          stored columnwise in the array ``p``.

        - ``homtrans(T, v)`` as above but ``v`` is a 1D array considered to be a column vector, and the
          retured value will be a column vector.


        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = trotx(0.3)
            >>> v = [1, 2, 3]
            >>> h2e( T @ e2h(v))
            >>> homtrans(T, v)

        .. note::

            - If T is a homogeneous transformation defining the pose of {B} with respect to {A},
              then the points are defined with respect to frame {B} and are transformed to be
              with respect to frame {A}.

        :seealso: :func:`e2h` :func:`h2e`

    isR(R: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], tol: float = 20) -> bool
        Test if matrix belongs to SO(n)

        :param R: matrix to test
        :type R: ndarray(2,2) or ndarray(3,3)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether matrix is a proper orthonormal rotation matrix
        :rtype: bool

        Checks orthogonality, ie. :math:`{\bf R} {\bf R}^T = {\bf I}` and :math:`\det({\bf R}) > 0`.
        For the first test we check that the norm of the residual is less than ``tol * eps``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> isR(np.eye(3))
            >>> isR(rot2(0.5))
            >>> isR(np.zeros((3,3)))

        :seealso: isrot2, isrot

    iseye(S: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], tol: float = 20) -> bool
        Test if matrix is identity

        :param S: matrix to test
        :type S: ndarray(n,n)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether matrix is a proper skew-symmetric matrix
        :rtype: bool

        Check if matrix is an identity matrix.
        We check that the sum of the absolute value of the residual is less than ``tol * eps``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> iseye(np.array([[1,0], [0,1]]))
            >>> iseye(np.array([[1,2], [0,1]]))

        :seealso: isskew, isskewa

    ishom(T: Any, check: bool = False, tol: float = 20) -> bool
        Test if matrix belongs to SE(3)

        :param T: SE(3) matrix to test
        :type T: numpy(4,4)
        :param check: check validity of rotation submatrix
        :param tol: Tolerance in units of eps for rotation submatrix check, defaults to 20
        :return: whether matrix is an SE(3) homogeneous transformation matrix

        - ``ishom(T)`` is True if the argument ``T`` is of dimension 4x4
        - ``ishom(T, check=True)`` as above, but also checks orthogonality of the
          rotation sub-matrix and validitity of the bottom row.

        .. runblock:: pycon

            >>> from spatialmath.base import ishom
            >>> import numpy as np
            >>> T = np.array([[1, 0, 0, 3], [0, 1, 0, 4], [0, 0, 1, 5], [0, 0, 0, 1]])
            >>> ishom(T)
            >>> T = np.array([[1, 1, 0, 3], [0, 1, 0, 4], [0, 0, 1, 5], [0, 0, 0, 1]]) # invalid SE(3)
            >>> ishom(T)  # a quick check says it is an SE(3)
            >>> ishom(T, check=True) # but if we check more carefully...
            >>> R = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]])
            >>> ishom(R)

        :seealso: :func:`~spatialmath.base.transformsNd.isR` :func:`~isrot` :func:`~spatialmath.base.transforms2d.ishom2`

    ishom2(T: Any, check: bool = False, tol: float = 20) -> bool
        Test if matrix belongs to SE(2)

        :param T: SE(2) matrix to test
        :type T: ndarray(3,3)
        :param check: check validity of rotation submatrix
        :type check: bool
        :param tol: Tolerance in units of eps for zero-rotation case, defaults to 20
        :type: float
        :return: whether matrix is an SE(2) homogeneous transformation matrix
        :rtype: bool

        - ``ishom2(T)`` is True if the argument ``T`` is of dimension 3x3
        - ``ishom2(T, check=True)`` as above, but also checks orthogonality of the
          rotation sub-matrix and validitity of the bottom row.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> T = np.array([[1, 0, 3], [0, 1, 4], [0, 0, 1]])
            >>> ishom2(T)
            >>> T = np.array([[1, 1, 3], [0, 1, 4], [0, 0, 1]]) # invalid SE(2)
            >>> ishom2(T)  # a quick check says it is an SE(2)
            >>> ishom2(T, check=True) # but if we check more carefully...
            >>> R = np.array([[1, 0], [0, 1]])
            >>> ishom2(R)

        :seealso: isR, isrot2, ishom, isvec

    ismatrix(m: Any, shape: Tuple[Optional[int], Optional[int]]) -> bool
        Test if argument is a real 2D matrix

        :param m: value to test
        :param shape: required shape
        :type shape: 2-tuple
        :return: True if value is of specified shape :rtype: bool

        Tests if the argument is a real 2D matrix with a specified shape ``shape``
        but the value ``None`` indicate an unspecified (wildcard, don't care)
        dimension, for example:

        .. runblock:: pycon

            >>> from spatialmath.base import ismatrix
            >>> import numpy as np
            >>> A = np.zeros((2,3))
            >>> ismatrix(A, (2,3))
            >>> ismatrix(A, (None,3))
            >>> ismatrix(A, (2,None))
            >>> ismatrix(A, (2,4))

        .. note:: Unlike ``verifymatrix`` this function: - checks the argument is
                    real valued - allows the shape to have an unspecified dimension

        :seealso: :func:`getmatrix`, :func:`verifymatrix`, :func:`assertmatrix`

    isnotebook() -> bool
        Determine if code is being run from a Jupyter notebook

        :references:

            - https://stackoverflow.com/questions/15411967/how-can-i-check-if-code-
            is-executed-in-the-ipython-notebook/39662359#39662359

    isnumberlist(x: Any) -> bool
        Test if argument is a list of scalars

        :param x: the value to test
        :return: True if the argument is a list of real scalars
        :rtype: bool

        ``isscalarlist(x)`` is ``True`` if ``x```` is a list of scalars.

        .. runblock:: pycon

            >>> from spatialmath.base import isnumberlist
            >>> import numpy as np
            >>> isnumberlist((1,2,3))
            >>> isnumberlist([1.1, 2.2, 3.3])
            >>> isnumberlist(1)
            >>> isnumberlist(np.r_[1,2])

    isrot(R: Any, check: bool = False, tol: float = 20) -> bool
        Test if matrix belongs to SO(3)

        :param R: SO(3) matrix to test
        :type R: numpy(3,3)
        :param check: check validity of rotation submatrix
        :param tol: Tolerance in units of eps for rotation matrix test, defaults to 20
        :return: whether matrix is an SO(3) rotation matrix

        - ``isrot(R)`` is True if the argument ``R`` is of dimension 3x3
        - ``isrot(R, check=True)`` as above, but also checks orthogonality of the
          rotation matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import isrot
            >>> import numpy as np
            >>> T = np.array([[1, 0, 0, 3], [0, 1, 0, 4], [0, 0, 1, 5], [0, 0, 0, 1]])
            >>> isrot(T)
            >>> R = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
            >>> isrot(R)
            >>> R = R = np.array([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) # invalid SO(3)
            >>> isrot(R)  # a quick check says it is an SO(3)
            >>> isrot(R, check=True) # but if we check more carefully...

        :seealso: :func:`~spatialmath.base.transformsNd.isR` :func:`~spatialmath.base.transforms2d.isrot2`,  :func:`~ishom`

    isrot2(R: Any, check: bool = False, tol: float = 20) -> bool
        Test if matrix belongs to SO(2)

        :param R: SO(2) matrix to test
        :type R: ndarray(3,3)
        :param check: check validity of rotation submatrix
        :type check: bool
        :param tol: Tolerance in units of eps for zero-rotation case, defaults to 20
        :type: float
        :return: whether matrix is an SO(2) rotation matrix
        :rtype: bool

        - ``isrot2(R)`` is True if the argument ``R`` is of dimension 2x2
        - ``isrot2(R, check=True)`` as above, but also checks orthogonality of the rotation matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> T = np.array([[1, 0, 3], [0, 1, 4], [0, 0, 1]])
            >>> isrot2(T)
            >>> R = np.array([[1, 0], [0, 1]])
            >>> isrot2(R)
            >>> R = np.array([[1, 1], [0, 1]])  # invalid SO(2)
            >>> isrot2(R)  # a quick check says it is an SO(2)
            >>> isrot2(R, check=True)  # but if we check more carefully...

        :seealso: isR, ishom2, isrot

    isscalar(x: Any) -> bool
        Test if argument is a real scalar

        :param x: value to test
        :return: whether value is a scalar
        :rtype: bool

        ``isscalar(x)`` is ``True`` if ``x`` is a Python or numPy int or real float.

        .. runblock:: pycon

            >>> from spatialmath.base import isscalar
            >>> isscalar(1)
            >>> isscalar(1.2)
            >>> isscalar([1])

    isskew(S: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], tol: float = 20) -> bool
        Test if matrix belongs to so(n)

        :param S: matrix to test
        :type S: ndarray(2,2) or ndarray(3,3)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether matrix is a proper skew-symmetric matrix
        :rtype: bool

        Checks skew-symmetry, ie. :math:`{\bf S} + {\bf S}^T = {\bf 0}`.
        We check that the norm of the residual is less than ``tol * eps``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> isskew(np.zeros((3,3)))
            >>> isskew(np.array([[0, -2], [2, 0]]))
            >>> isskew(np.eye(3))

        :seealso: isskewa

    isskewa(S: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], tol: float = 20) -> bool
        Test if matrix belongs to se(n)

        :param S: matrix to test
        :type S: ndarray(3,3) or ndarray(4,4)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether matrix is a proper skew-symmetric matrix
        :rtype: bool

        Check if matrix is augmented skew-symmetric, ie. the top left (n-1xn-1) partition ``S`` is
        skew-symmetric :math:`{\bf S} + {\bf S}^T = {\bf 0}`, and the bottom row is zero
        We check that the norm of the residual is less than ``tol * eps``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> isskewa(np.zeros((3,3)))
            >>> isskewa(np.array([[0, -2], [2, 0]])) # this matrix is skew but not skewa
            >>> isskewa(np.array([[0, -2, 5], [2, 0, 6], [0, 0, 0]]))

        :seealso: isskew

    isunittwist(v: Union[List[float], Tuple[float, float, float, float, float, float], numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]], tol: float = 20) -> bool
        Test if vector represents a unit twist in SE(2) or SE(3)

        :param v: twist vector to test
        :type v: array_like(6)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether twist has unit length
        :rtype: bool
        :raises ValueError: for incorrect vector length


        Vector is is intepretted as :math:`[v, \omega]` where :math:`v \in \mathbb{R}^n` and
        :math:`\omega \in \mathbb{R}^1` for SE(2) and :math:`\omega \in \mathbb{R}^3` for SE(3).

        A unit twist can be a:

        - unit rotational twist where :math:`|| \omega || = 1`, or
        - unit translational twist where :math:`|| \omega || = 0` and :math:`|| v || = 1`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> isunittwist([1, 2, 3, 1, 0, 0])
            >>> isunittwist([0, 0, 0, 2, 0, 0])

        :seealso: unit, isunitvec

    isunittwist2(v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], tol: float = 20) -> bool
        Test if vector represents a unit twist in SE(2) or SE(3)

        :param v: twist vector to test
        :type v: array_like(3)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether vector has unit length
        :rtype: bool
        :raises ValueError: for incorrect vector length

        Vector is is intepretted as :math:`[v, \omega]` where :math:`v \in \mathbb{R}^n` and
        :math:`\omega \in \mathbb{R}^1` for SE(2) and :math:`\omega \in \mathbb{R}^3` for SE(3).

        A unit twist can be a:

        - unit rotational twist where :math:`|| \omega || = 1`, or
        - unit translational twist where :math:`|| \omega || = 0` and :math:`|| v || = 1`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> isunittwist2([1, 2, 1])
            >>> isunittwist2([0, 0, 2])

        :seealso: unit, isunitvec

    isunitvec(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], tol: float = 20) -> bool
        Test if vector has unit length

        :param v: vector to test
        :type v: ndarray(n)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether vector has unit length
        :rtype: bool

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> isunitvec([1, 0])
            >>> isunitvec([1, 2])

        :seealso: unit, iszerovec, isunittwist

    isvector(v: Any, dim: Optional[int] = None) -> bool
        Test if argument is a real vector

        :param v: value to test
        :param dim: required dimension
        :type dim: int or None
        :return: whether value is a valid vector
        :rtype: bool

        - ``isvector(vec)`` is ``True`` if ``vec`` is a vector, ie. any of:

            - a Python native int or float, a 1-vector
            - Python native list or tuple
            - numPy real 1D array, ie. shape=(N,)
            - numPy real 2D array with a singleton dimension, ie. shape=(1,N)
              or (N,1)

        - ``isvector(vec, N)`` as above but must also be an ``N``-element vector.

        .. runblock:: pycon

            >>> from spatialmath.base import isvector
            >>> import numpy as np
            >>> isvector([1,2])  # list
            >>> isvector((1,2))  # tuple
            >>> isvector(np.r_[1,2,3])  # numpy array
            >>> isvector(1)  # scalar
            >>> isvector([1,2], 3)  # list

        :seealso: :func:`getvector`, :func:`assertvector`

    isvectorlist(x: Any, n: int) -> bool
        Test if argument is a list of vectors

        :param x: the value to test
        :return: True if the argument is a list of n-vectors
        :rtype: bool

        ``isvectorlist(x, n)`` is ``True`` if ``x`` is a list or tuple of
        1D numPy arrays of shape=(n,).


        .. runblock:: pycon

            >>> from spatialmath.base import isvectorlist
            >>> import numpy as np
            >>> isvectorlist([np.r_[1,2], np.r_[3,4], np.r_[5,6]], 2)
            >>> isvectorlist([(1,2), (3,4), (5,6)], 2)
            >>> isvectorlist([np.r_[1,2], np.r_[3,4], np.r_[5,6,7]], 2)

    iszero(v: float, tol: float = 20) -> bool
        Test if scalar is zero

        :param v: value to test
        :type v: float
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether value is zero
        :rtype: bool

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> iszero(0)
            >>> iszero(1)

        :seealso: unit, iszerovec, isunittwist

    iszerovec(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], tol: float = 20) -> bool
        Test if vector has zero length

        :param v: vector to test
        :type v: ndarray(n)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether vector has zero length
        :rtype: bool

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> iszerovec([0, 0])
            >>> iszerovec([1, 2])

        :seealso: unit, isunitvec, isunittwist

    mpq_point(data: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], p: int, q: int) -> float
        Moments of polygon

        :param data: polygon vertices, points as columns
        :type data: ndarray(2,N)
        :param p: moment order x
        :type p: int
        :param q: moment order y
        :type q: int

        Returns the pq'th moment of the polygon

        .. math::

            M(p, q) = \sum_{i=0}^{n-1} x_i^p y_i^q

        Example:

        .. runblock:: pycon

            >>> from spatialmath.base import mpq_point
            >>> import numpy as np
            >>> p = np.array([[1, 3, 2], [2, 2, 4]])
            >>> mpq_point(p, 0, 0)  # area
            >>> mpq_point(p, 3, 0)

        .. note:: is negative for clockwise perimeter.

    norm(v: Union[List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> float
        Norm of vector

        :param v: any vector
        :type v: array_like(n)
        :return: norm of vector
        :rtype: float

        ``norm(v)`` is the 2-norm (length or magnitude) of the vector ``v``.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> norm([3, 4])

        .. note:: This function does not use NumPy, it is ~2x faster than
            `numpy.linalg.norm()` for a 3-vector

        :seealso: :func:`~spatialmath.base.unit`

        :SymPy: supported

    normsq(v: Union[List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> float
        Squared norm of vector

        :param v: any vector
        :type v: array_like(n)
        :return: norm of vector
        :rtype: float

        ``norm(sq)`` is the sum of squared elements of the vector ``v``
        or :math:`|v|^2`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> normsq([2, 3])

        .. note:: This function does not use NumPy, it is ~2x faster than
            `numpy.linalg.norm() ** 2` for a 3-vector

        :seealso: :func:`~spatialmath.base.unit`

        :SymPy: supported

    numhess(J: Callable, x: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], dx: float = 1e-08)
        Numerically compute Hessian given Jacobian function

        :param J: the Jacobian function, returns an ndarray(m,n)
        :type J: callable
        :param x: function argument
        :type x: ndarray(n)
        :param dx: the numerical perturbation, defaults to 1e-8
        :type dx: float, optional
        :return: Hessian matrix
        :rtype: ndarray(m,n,n)

        Computes a numerical approximation to the Hessian for ``J(x)`` where
        :math:`f: \mathbb{R}^n  \mapsto \mathbb{R}^{m \times n}`.

        The result is a 3D array where

        .. math::

            H_{i,j,k} = \frac{\partial J_{j,k}}{\partial x_i}

        Uses first-order difference :math:`H[:,:,i] = (J(x + dx) - J(x)) / dx`.

    numjac(f: Callable, x: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], dx: float = 1e-08, SO: int = 0, SE: int = 0) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Numerically compute Jacobian of function

        :param f: the function, returns an m-vector
        :type f: callable
        :param x: function argument
        :type x: ndarray(n)
        :param dx: the numerical perturbation, defaults to 1e-8
        :type dx: float, optional
        :param SO: function returns SO(N) matrix, defaults to 0
        :type SO: int, optional
        :param SE: function returns SE(N) matrix, defaults to 0
        :type SE: int, optional

        :return: Jacobian matrix
        :rtype: ndarray(m,n)

        Computes a numerical approximation to the Jacobian for ``f(x)`` where
        :math:`f: \mathbb{R}^n \mapsto \mathbb{R}^m`.

        Uses first-order difference :math:`J[:,i] = (f(x + dx) - f(x)) / dx`.

        If ``SO`` is 2 or 3, then it is assumed that the function returns
        an SO(N) matrix and the derivative is converted to a column vector

        .. math::

            \vex{\dmat{R} \mat{R}^T}

        If ``SE`` is 2 or 3, then it is assumed that the function returns
        an SE(N) matrix and the derivative is converted to a colun vector.

        Example:

            .. runblock:: pycon

                >>> from spatialmath.base import rotx, numjac
                >>> numjac(rotx, [0])
                >>> numjac(rotx, [0], SO=3)

    oa2r(o: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], a: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SO(3) rotation matrix from two vectors

        :param o: 3D vector parallel to Y- axis
        :type o: array_like(3)
        :param a: 3D vector parallel to the Z-axis
        :type o: array_like(3)
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        ``T = oa2tr(O, A)`` is an SO(3) orthonormal rotation matrix for a frame
        defined in terms of vectors parallel to its Y- and Z-axes with respect to a
        reference frame.  In robotics these axes are respectively called the
        orientation and approach vectors defined such that R = [N O A] and N = O x
        A.

        Steps:

            1. N' = O x A
            2. O' = A x N
            3. normalize N', O', A
            4. stack horizontally into rotation matrix

        .. runblock:: pycon

            >>> from spatialmath.base import oa2r
            >>> oa2r([0, 1, 0], [0, 0, -1])  # Y := Y, Z := -Z

        .. note::

            - The A vector is the only guaranteed to have the same direction in the
              resulting rotation matrix
            - O and A do not have to be unit-length, they are normalized
            - O and A do not have to be orthogonal, so long as they are not parallel
            - The vectors O and A are parallel to the Y- and Z-axes of the
              equivalent coordinate frame.

        :seealso: :func:`~oa2tr`

        :SymPy: not supported

    oa2tr(o: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], a: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create SE(3) pure rotation from two vectors

        :param o: 3D vector parallel to Y- axis
        :type o: array_like(3)
        :param a: 3D vector parallel to the Z-axis
        :type o: array_like(3)
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        ``T = oa2tr(O, A)`` is an SE(3) homogeneous transformation matrix for a
        frame defined in terms of vectors parallel to its Y- and Z-axes with respect
        to a reference frame.  In robotics these axes are respectively called the
        orientation and approach vectors defined such that R = [N O A] and N = O x
        A.

        Steps:

            1. N' = O x A
            2. O' = A x N
            3. normalize N', O', A
            4. stack horizontally into rotation matrix

        .. runblock:: pycon

            >>> from spatialmath.base import oa2tr
            >>> oa2tr([0, 1, 0], [0, 0, -1])  # Y := Y, Z := -Z

        .. note:

            - The A vector is the only guaranteed to have the same direction in the
              resulting rotation matrix
            - O and A do not have to be unit-length, they are normalized
            - O and A do not have to be orthogonal, so long as they are not parallel
            - The translational part is zero.
            - The vectors O and A are parallel to the Y- and Z-axes of the
              equivalent coordinate frame.

        :seealso: :func:`~oa2r`

        :SymPy: not supported

    plot_arrow(start: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], end: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], label: Optional[str] = None, label_pos: str = 'above:0.5', ax: Optional[matplotlib.axes._axes.Axes] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Plot 2D arrow

        :param start: start point, arrow tail
        :type start: array_like(2)
        :param end: end point, arrow head
        :type end: array_like(2)
        :param label: arrow label text, optional
        :type label: str
        :param label_pos: position of arrow label "above|below:fraction", optional
        :type label_pos: str
        :param ax: axes to draw into, defaults to None
        :type ax: Axes, optional
        :param kwargs: argumetns to pass to :class:`matplotlib.patches.Arrow`

        Draws an arrow from ``start`` to ``end``.

        A ``label``, if given, is drawn above or below the arrow.  The position of the
        label is controlled by ``label_pos`` which is of the form
        ``"position:fraction"`` where ``position`` is either ``"above"`` or ``"below"``
        the arrow, and ``fraction`` is a float between 0 (tail) and 1 (head) indicating
        the distance along the arrow where the label will be placed.  The text is
        suitably justified to not overlap the arrow.

        Example::

            >>> from spatialmath.base import plotvol2, plot_arrow
            >>> plotvol2(5)
            >>> plot_arrow((-2, 2), (2, 4), color='r', width=0.1)  # red arrow
            >>> plot_arrow((4, 1), (2, 4), color='b', width=0.1)  # blue arrow

        .. plot::

            from spatialmath.base import plotvol2, plot_arrow
            ax = plotvol2(5)
            plot_arrow((-2, 2), (3, 4), color='r', width=0.1)  # red arrow
            plot_arrow((4, 1), (3, 4), color='b', width=0.1)  # blue arrow
            ax.grid()

        Example::

            >>> from spatialmath.base import plotvol2, plot_arrow
            >>> plotvol2(5)
            >>> plot_arrow((-2, -2), (2, 4), label=r"$\mathit{p}_3$", color='r', width=0.1)

        .. plot::

            from spatialmath.base import plotvol2, plot_arrow
            ax = plotvol2(5)
            ax.grid()
            plot_arrow(
                (-2, -2), (2, 4), label="$\mathit{p}_3$", color="r", width=0.1
            )
            plt.show(block=True)

        :seealso: :func:`plot_homline`

    plot_box(*fmt: Optional[str], lbrt: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], NoneType] = None, lrbt: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], NoneType] = None, lbwh: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], NoneType] = None, bbox: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], NoneType] = None, ltrb: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], NoneType] = None, lb: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, lt: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, rb: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, rt: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, wh: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, w: Optional[float] = None, h: Optional[float] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, filled: bool = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a 2D box using matplotlib

        :param lb: left-bottom corner, defaults to None
        :type lb: array_like(2), optional
        :param lt: left-top corner, defaults to None
        :type lt: array_like(2), optional
        :param rb: right-bottom corner, defaults to None
        :type rb: array_like(2), optional
        :param rt: right-top corner, defaults to None
        :type rt: array_like(2), optional
        :param wh: width and height, if both are the same provide scalar, defaults to None
        :type wh: scalar, array_like(2), optional
        :param centre: centre of box, defaults to None
        :type centre: array_like(2), optional
        :param w: width of box, defaults to None
        :type w: float, optional
        :param h: height of box, defaults to None
        :type h: float, optional
        :param ax: the axes to draw on, defaults to ``gca()``
        :type ax: Axis, optional
        :param bbox: bounding box matrix, defaults to None
        :type bbox: array_like(4), optional
        :param color: box outline color
        :type color: array_like(3) or str
        :param fillcolor: box fill color
        :type fillcolor: array_like(3) or str
        :param alpha: transparency, defaults to 1
        :type alpha: float, optional
        :param thickness: line thickness, defaults to None
        :type thickness: float, optional
        :return: the matplotlib object
        :rtype: Patch.Rectangle instance

        The box can be specified in many ways:

        - bounding box [xmin, xmax, ymin, ymax]
        - alternative box [xmin, ymin, xmax, ymax]
        - centre and width+height
        - left-bottom and right-top corners
        - left-bottom corner and width+height
        - right-top corner and width+height
        - left-top corner and width+height

        For plots where the y-axis is inverted (eg. for images) then top is the
        smaller vertical coordinate.

        Example::

            >>> plotvol2(5)
            >>> plot_box("b--", centre=(2, 3), wh=1)  # w=h=1
            >>> plot_box(lt=(0, 0), rb=(3, -2), filled=True, color="r")

        .. plot::

            from spatialmath.base import plotvol2, plot_box
            ax = plotvol2(5)
            plot_box("b--", centre=(2, 3), wh=1)  # w=h=1
            plot_box(lt=(0, 0), rb=(3, -2), filled=True, hatch="/", edgecolor="k", color="r")
            ax.grid()

    plot_circle(radius: float, centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], *fmt: Optional[str], resolution: Optional[int] = 50, ax: Optional[matplotlib.axes._axes.Axes] = None, filled: Optional[bool] = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a circle using matplotlib

        :param centre: centre of circle, defaults to (0,0)
        :type centre: array_like(2), optional
        :param args:
        :param radius: radius of circle
        :type radius: float
        :param resolution: number of points on circumference, defaults to 50
        :type resolution: int, optional
        :return: the matplotlib object
        :rtype: list of Line2D or Patch.Polygon

        Plot or more circles. If ``centre`` is a 3xN array, then each column is
        taken as the centre of a circle.  All circles have the same radius, color
        etc.

        Example::

            >>> from spatialmath.base import plotvol2, plot_circle
            >>> plotvol2(5)
            >>> plot_circle(1, (0,0), 'r')  # red circle
            >>> plot_circle(2, (1, 2), 'b--')  # blue dashed circle
            >>> plot_circle(0.5, (3,4), filled=True, facecolor='y')  # yellow filled circle

        .. plot::

            from spatialmath.base import plotvol2, plot_circle
            ax = plotvol2(5)
            plot_circle(1, (0,0), 'r')  # red circle
            plot_circle(2, (1, 2), 'b--')  # blue dashed circle
            plot_circle(0.5, (3,4), filled=True, facecolor='y')  # yellow filled circle
            ax.grid()

    plot_cone(radius: float, height: float, resolution: Optional[int] = 50, flip: Optional[bool] = False, centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), ends: Optional[bool] = False, pose: Optional[numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, filled: Optional[bool] = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a cone using matplotlib

        :param radius: radius of cone at open end
        :param height: height of cone in the z-direction
        :param resolution: number of points on circumferece, defaults to 50
        :param flip: cone faces upward, defaults to False
        :param ends: add a surface for the base of the cone
        :param pose: pose of cone, defaults to None
        :type pose: SE3, optional
        :param ax: axes to draw into, defaults to None
        :param filled: draw filled polygon, else wireframe, defaults to False
        :type filled: bool, optional
        :param kwargs: arguments passed to ``plot_wireframe`` or ``plot_surface``

        :return: matplotlib objects
        :rtype: list of matplotlib object types

        The axis of the cone is parallel to the z-axis and it is drawn pointing
        down. The point is at z=0 and the open end at z= ``height``.  If ``flip`` is
        True then the cone faces upwards, the point is at z= ``height`` and the open
        end at z=0.

        The cylinder can be positioned by setting ``centre``, or positioned
        and orientated by setting ``pose``.

        Example::

            >>> plot_cone(radius=1, height=2)

        .. plot::

            from spatialmath.base import plot_cone, plotvol3

            plotvol3(5)
            plot_cone(radius=1, height=2)

        :seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    plot_cuboid(sides: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]] = (1, 1, 1), centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), pose: Optional[numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, filled: Optional[bool] = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a cuboid (3D box) using matplotlib

        :param sides: side lengths, defaults to 1
        :type sides: array_like(3), optional
        :param centre: centre of box, defaults to (0, 0, 0)
        :type centre: array_like(3), optional

        :param pose: pose of sphere, defaults to None
        :type pose: SE3, optional
        :param ax: axes to draw into, defaults to None
        :type ax: Axes3D, optional
        :param filled: draw filled polygon, else wireframe, defaults to False
        :type filled: bool, optional
        :param kwargs: arguments passed to ``plot_wireframe`` or ``plot_surface``

        :return: matplotlib collection
        :rtype: Line3DCollection or Poly3DCollection

        Example::

            >>> plot_cone(radius=1, height=2)

        .. plot::

            from spatialmath.base import plot_cuboid, plotvol3

            plotvol3(5)
            plot_cuboid(sides=(3,2,1), centre=(0,1,2))

        :seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    plot_cylinder(radius: float, height: Union[float, List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], resolution: Optional[int] = 50, centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), ends=False, pose: Optional[numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]] = None, ax=None, filled=False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a cylinder using matplotlib

        :param radius: radius of cylinder
        :type radius: float
        :param height: height of cylinder in the z-direction
        :type height: float or array_like(2)
        :param resolution: number of points on circumference, defaults to 50
        :param centre: position of centre
        :param pose: pose of cylinder, defaults to None
        :type pose: SE3, optional
        :param ax: axes to draw into, defaults to None
        :type ax: Axes3D, optional
        :param filled: draw filled polygon, else wireframe, defaults to False
        :type filled: bool, optional
        :param kwargs: arguments passed to ``plot_wireframe`` or ``plot_surface``

        :return: matplotlib objects
        :rtype: list of matplotlib object types

        The axis of the cylinder is parallel to the z-axis and extends from z=0
        to z=height, or z=height[0] to z=height[1].

        The cylinder can be positioned by setting ``centre``, or positioned
        and orientated by setting ``pose``.

        Example::

            >>> plot_cylinder(radius=1, height=(1,3))

        .. plot::

            from spatialmath.base import plot_cylinder, plotvol3

            plotvol3(5)
            plot_cylinder(radius=1, height=(1,3))


        :seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    plot_ellipse(E: numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]], numpy.dtype[numpy.floating]], centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], *fmt: Optional[str], scale: Optional[float] = 1, confidence: Optional[float] = None, resolution: Optional[int] = 40, inverted: Optional[bool] = False, ax: Optional[matplotlib.axes._axes.Axes] = None, filled: Optional[bool] = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot an ellipse using matplotlib

        :param E: matrix describing ellipse
        :type E: ndarray(2,2)
        :param centre: centre of ellipse, defaults to (0, 0)
        :type centre: array_like(2), optional
        :param scale: scale factor for the ellipse radii
        :type scale: float
        :param resolution: number of points on circumferece, defaults to 40
        :type resolution: int, optional
        :return: the matplotlib object
        :rtype: Line2D or Patch.Polygon

        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
            - for robot manipulability
            :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``.

        Returns a set of ``resolution``  that lie on the circumference of a circle
        of given ``center`` and ``radius``.

        Example:

            >>> from spatialmath.base import plotvol2, plot_ellipse
            >>> plotvol2(5)
            >>> plot_ellipse(np.array([[1, 1], [1, 2]]), [0,0], 'r')  # red ellipse
            >>> plot_ellipse(np.array([[1, 1], [1, 2]]), [1, 2], 'b--')  # blue dashed ellipse
            >>> plot_ellipse(np.array([[1, 1], [1, 2]]), [-2, -1], filled=True, facecolor='y')  # yellow filled ellipse

        .. plot::

            from spatialmath.base import plotvol2, plot_ellipse
            ax = plotvol2(5)
            plot_ellipse(np.array([[1, 1], [1, 2]]), [0,0], 'r')  # red ellipse
            plot_ellipse(np.array([[1, 1], [1, 2]]), [1, 2], 'b--')  # blue dashed ellipse
            plot_ellipse(np.array([[1, 1], [1, 2]]), [-2, -1], filled=True, facecolor='y')  # yellow filled ellipse
            ax.grid()

    plot_ellipsoid(E: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]], centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), scale: Optional[float] = 1, confidence: Optional[float] = None, resolution: Optional[int] = 40, inverted: Optional[bool] = False, ax: Optional[matplotlib.axes._axes.Axes] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Draw an ellipsoid using matplotlib

        :param E: ellipsoid
        :type E: ndarray(3,3)
        :param centre: [description], defaults to (0,0,0)
        :type centre: tuple, optional
        :param scale:
        :type scale:
        :param confidence: confidence interval, range 0 to 1
        :type confidence: float
        :param resolution: number of points on circumferece, defaults to 40
        :type resolution: int, optional
        :param inverted: :math:`E^{-1}` rather than :math:`E` provided, defaults to False
        :type inverted: bool, optional
        :param ax: [description], defaults to None
        :type ax: [type], optional
        :param wireframe: [description], defaults to False
        :type wireframe: bool, optional
        :param stride: [description], defaults to 1
        :type stride: int, optional

        ``plot_ellipsoid(E)`` draws the ellipsoid defined by :math:`x^T \mat{E} x = 0`
        on the current plot.

        Example::

            >>> plot_ellipsoid(np.diag([1, 2, 3]), [1, 1, 0], color="r", resolution=10); # draw red ellipsoid

        .. plot::

            from spatialmath.base import plot_ellipsoid, plotvol3
            import numpy as np

            plotvol3(4)
            plot_ellipsoid(np.diag([1, 2, 3]), [1, 1, 0], color="r", resolution=5); # draw red 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.

        :seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    plot_homline(lines: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]], *args, ax: Optional[matplotlib.axes._axes.Axes] = None, xlim: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, ylim: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Plot homogeneous lines using matplotlib

        :param lines: homgeneous line or lines
        :type lines: array_like(3), ndarray(3,N)
        :param ax: axes to plot in, defaults to ``gca()``
        :type ax: Axis, optional
        :param kwargs: arguments passed to ``plot``
        :return: matplotlib object
        :rtype: list of Line2D instances

        Draws the 2D line given in homogeneous form :math:`\ell[0] x + \ell[1] y + \ell[2] = 0` in the current
        2D axes.

        .. warning: A set of 2D axes must exist in order that the axis limits can
            be obtained. The line is drawn from edge to edge.

        If ``lines`` is a 3xN array then ``N`` lines are drawn, one per column.

        Example::

            >>> from spatialmath.base import plotvol2, plot_homline
            >>> plotvol2(5)
            >>> plot_homline((1, -2, 3))
            >>> plot_homline((1, -2, 3), 'k--') # dashed black line

        .. plot::

            from spatialmath.base import plotvol2, plot_homline
            ax = plotvol2(5)
            plot_homline((1, -2, 3))
            plot_homline((1, -2, 3), 'k--') # dashed black line
            ax.grid()

        :seealso: :func:`plot_arrow`

    plot_point(pos: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], marker: Optional[str] = 'bs', text: Optional[str] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, textargs: Optional[dict] = None, textcolor: Union[str, List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a point using matplotlib

        :param pos: position of marker
        :type pos: array_like(2), ndarray(2,n), list of 2-tuples
        :param marker: matplotlub marker style, defaults to 'bs'
        :type marker: str or list of str, optional
        :param text: text label, defaults to None
        :type text: str, optional
        :param ax: axes to plot in, defaults to ``gca()``
        :type ax: Axis, optional
        :return: the matplotlib object
        :rtype: list of Text and Line2D instances

        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.

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

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

        - Multiple points can be marked if ``pos`` is a 2xn array or a list of
        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
            - ``text`` can be a tuple containing a format string followed by vectors
            of shape(n).  For example::

                ``("#{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
            >>> plotvol2(5)
            >>> 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::

            from spatialmath.base import plotvol2, plot_text
            ax = plotvol2(5)
            plot_point((0, 0))
            plot_point((1,1), 'r*')
            plot_point((2,2), 'r*', 'foo')
            ax.grid()

        Plot red star at points defined by columns of ``p`` and label them sequentially
        from 0::

            >>> p = np.random.uniform(size=(2,10), low=-5, high=5)
            >>> plotvol2(5)
            >>> plot_point(p, 'r*', '{0}')

        .. plot::

            from spatialmath.base import plotvol2, plot_point
            import numpy as np
            p = np.random.uniform(size=(2,10), low=-5, high=5)
            ax = plotvol2(5)
            plot_point(p, 'r*', '{0}')
            ax.grid()

        Plot red star at points defined by columns of ``p`` and label them all with
        successive elements of ``z``

            >>> p = np.random.uniform(size=(2,10), low=-5, high=5)
            >>> value = np.random.uniform(size=(1,10))
            >>> plotvol2(5)
            >>> plot_point(p, 'r*', ('{1:.2f}', value))

        .. plot::

            from spatialmath.base import plotvol2, plot_point
            import numpy as np
            p = np.random.uniform(size=(2,10), low=-5, high=5)
            value = np.random.uniform(size=(10,))
            ax = plotvol2(5)
            plot_point(p, 'r*', ('{1:.2f}', value))
            ax.grid()

        :seealso: :func:`plot_text`

    plot_polygon(vertices: numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]], *fmt, close: Optional[bool] = False, **kwargs) -> List[matplotlib.artist.Artist]
        Plot polygon

        :param vertices: vertices
        :type vertices: ndarray(2,N)
        :param close: close the polygon, defaults to False
        :type close: bool, optional
        :param kwargs: arguments passed to Patch
        :return: Matplotlib artist
        :rtype: line or patch

        Example::

            >>> from spatialmath.base import plotvol2, plot_polygon
            >>> plotvol2(5)
            >>> vertices = np.array([[-1, 2, -1], [1, 0, -1]])
            >>> plot_polygon(vertices, filled=True, facecolor='g')  # green filled triangle

        .. plot::

            from spatialmath.base import plotvol2, plot_polygon
            ax = plotvol2(5)
            vertices = np.array([[-1, 2, -1], [1, 0, -1]])
            plot_polygon(vertices, filled=True, facecolor='g')  # green filled triangle
            ax.grid()

    plot_sphere(radius: float, centre: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), pose: Optional[numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]] = None, resolution: Optional[int] = 50, ax: Optional[matplotlib.axes._axes.Axes] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Plot a sphere using matplotlib

        :param centre: centre of sphere, defaults to (0, 0, 0)
        :type centre: array_like(3), ndarray(3,N), optional
        :param radius: radius of sphere, defaults to 1
        :type radius: float, optional
        :param resolution: number of points on circumferece, defaults to 50
        :type resolution: int, optional

        :param pose: pose of sphere, defaults to None
        :type pose: SE3, optional
        :param ax: axes to draw into, defaults to None
        :type ax: Axes3D, optional
        :param filled: draw filled polygon, else wireframe, defaults to False
        :type filled: bool, optional
        :param kwargs: arguments passed to ``plot_wireframe`` or ``plot_surface``

        :return: matplotlib collection
        :rtype: list of Line3DCollection or Poly3DCollection

        Plot one or more spheres. If ``centre`` is a 3xN array, then each column is
        taken as the centre of a sphere.  All spheres have the same radius, color
        etc.

        Example::

            >>> from spatialmath.base import plot_sphere
            >>> plot_sphere(radius=1, color="r", resolution=10)   # red sphere wireframe
            >>> plot_sphere(radius=1, centre=(1,1,1), filled=True, facecolor='b')


        .. plot::

            from spatialmath.base import plot_sphere, plotvol3

            plotvol3(2)
            plot_sphere(radius=1, color='r', resolution=5)   # red sphere wireframe

        .. plot::

            from spatialmath.base import plot_sphere, plotvol3

            plotvol3(5)
            plot_sphere(radius=1, centre=(1,1,1), filled=True, facecolor='b')


        :seealso: :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    plot_text(pos: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]], text: str, ax: Optional[matplotlib.axes._axes.Axes] = None, color: Union[str, List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None, **kwargs) -> List[matplotlib.artist.Artist]
        Plot text using matplotlib

        :param pos: position of text
        :type pos: array_like(2)
        :param text: text
        :type text: str
        :param ax: axes to draw in, defaults to ``gca()``
        :type ax: Axis, optional
        :param color: text color, defaults to None
        :type color: str or array_like(3), optional
        :param kwargs: additional arguments passed to ``pyplot.text()``
        :return: the matplotlib object
        :rtype: list of Text instance

        Example::

            >>> from spatialmath.base import plotvol2, plot_text
            >>> plotvol2(5)
            >>> plot_text((1,3), 'foo')
            >>> plot_text((2,2), 'bar', color='b')
            >>> plot_text((2,2), 'baz', fontsize=14, horizontalalignment='centre')

        .. plot::

            from spatialmath.base import plotvol2, plot_text
            ax = plotvol2(5)
            plot_text((0,0), 'foo')
            plot_text((1,1), 'bar', color='b')
            plot_text((2,2), 'baz', fontsize=14, horizontalalignment='center')
            ax.grid()

        :seealso: :func:`plot_point`

    plotvol2(dim: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, equal: Optional[bool] = True, grid: Optional[bool] = False, labels: Optional[bool] = True, new: Optional[bool] = False) -> matplotlib.axes._axes.Axes
        Create 2D plot area

        :param ax: axes of initializer, defaults to new subplot
        :type ax: AxesSubplot, optional
        :param equal: set aspect ratio to 1:1, default False
        :type equal: bool
        :return: initialized axes
        :rtype: AxesSubplot

        Initialize axes with dimensions given by ``dim`` which can be:

        ==============  ======  ======
        input           xrange  yrange
        ==============  ======  ======
        A (scalar)      -A:A    -A:A
        [A, B]           A:B     A:B
        [A, B, C, D]     A:B     C:D
        ==============  ======  ======

        :seealso: :func:`plotvol3`, :func:`expand_dims`

    plotvol3(dim: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]] = None, ax: Optional[matplotlib.axes._axes.Axes] = None, equal: Optional[bool] = True, grid: Optional[bool] = False, labels: Optional[bool] = True, projection: Optional[str] = 'ortho', new: Optional[bool] = False) -> mpl_toolkits.mplot3d.axes3d.Axes3D
        Create 3D plot volume

        :param ax: axes of initializer, defaults to new subplot
        :type ax: Axes3DSubplot, optional
        :param equal: set aspect ratio to 1:1:1, default False
        :type equal: bool
        :return: initialized axes
        :rtype: Axes3DSubplot

        Initialize axes with dimensions given by ``dim`` which can be:

        ==================  ======  ======  =======
        input               xrange  yrange  zrange
        ==================  ======  ======  =======
        A (scalar)          -A:A    -A:A    -A:A
        [A, B]              A:B     A:B     A:B
        [A, B, C, D, E, F]  A:B     C:D     E:F
        ==================  ======  ======  =======

        :seealso: :func:`plotvol2`, :func:`expand_dims`

    q2r(q: Union[numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]], List[float], Tuple[float, float, float, float]], order: Optional[str] = 'sxyz') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert unit-quaternion to SO(3) rotation matrix

        :arg q: unit-quaternion
        :type v: array_like(4)
        :param order: the order of the quaternion elements. Must be 'sxyz' or
            'xyzs'. Defaults to 'sxyz'.
        :type order: str
        :return: corresponding SO(3) rotation matrix
        :rtype: ndarray(3,3)

        Returns an SO(3) rotation matrix corresponding to this unit-quaternion.

        .. runblock:: pycon

            >>> from spatialmath.base import q2r
            >>> q = [0, 0, 1, 0]  # rotation of 180deg about y-axis
            >>> print(q2r(q))

        .. warning:: There is no check that the passed value is a unit-quaternion.

        :seealso: :func:`r2q`

    q2str(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], delim: Optional[Tuple[str, str]] = ('<', '>'), fmt: Optional[str] = '{: .4f}') -> str
        Format a quaternion as a string

        :arg q: unit-quaternion
        :type q: array_like(4)
        :arg delim: 2-list of delimeters [default ('<', '>')]
        :type delim: list or tuple of strings
        :arg fmt: printf-style format soecifier [default '{: .4f}']
        :type fmt: str
        :return: formatted string
        :rtype: str

        Format the quaternion in a human-readable form as::

            S  D1  VX VY VZ D2

        where S, VX, VY, VZ are the quaternion elements, and D1 and D2 are a pair
        of delimeters given by `delim`.

        .. runblock:: pycon

            >>> from spatialmath.base import q2str, qrand
            >>> q = [1, 2, 3, 4]
            >>> q2str(q)
            >>> q = qrand()   # a unit quaternion
            >>> q2str(q, delim=('<<', '>>'))

        :seealso: :meth:`qprint`

    q2v(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert unit-quaternion to 3-vector

        :arg q: unit-quaternion
        :type v: array_like(4)
        :return: a unique 3-vector
        :rtype: ndarray(3)

        Returns a unique 3-vector representing the input unit-quaternion. The sign
        of the scalar part is made positive, if necessary by multiplying the
        entire quaternion by -1, then the vector part is taken.

        .. runblock:: pycon

            >>> from spatialmath.base import q2v
            >>> from math import sqrt
            >>> q = [1 / sqrt(2), 0, 1 / sqrt(2), 0]
            >>> print(q2v(q))
            >>> q = [-1 / sqrt(2), 0, 1 / sqrt(2), 0]
            >>> print(q2v(q))

        .. warning:: There is no check that the passed value is a unit-quaternion.

        :seealso: :func:`v2q`

    qangle(q1: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], q2: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> float
        Angle between two unit-quaternions

        :arg q0: unit-quaternion
        :type q0: array_like(4)
        :arg q1: unit-quaternion
        :type q1: array_like(4)
        :return: angle between the rotations [radians]
        :rtype: float

        If each of the input quaternions is considered a rotated coordinate
        frame, then the angle is the smallest rotation required about a fixed
        axis, to rotate the first frame into the second.

        .. runblock:: pycon

            >>> from spatialmath.base import qangle
            >>> from math import sqrt
            >>> q1 = [1/sqrt(2), 1/sqrt(2), 0, 0]    # 90deg rotation about x-axis
            >>> q2 = [1/sqrt(2), 0, 1/sqrt(2), 0]    # 90deg rotation about y-axis
            >>> qangle(q1, q2)

        :References:

        - Metrics for 3D rotations: comparison and analysis,
          Du Q. Huynh, % J.Math Imaging Vis. DOFI 10.1007/s10851-009-0161-2.

        .. warning:: There is no check that the passed values are unit-quaternions.

    qconj(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Quaternion conjugate

        :arg q: quaternion
        :type v: array_like(4)
        :return: conjugate of input quaternion
        :rtype: ndarray(4)

        Conjugate of quaternion, the vector part is negated.

        .. runblock:: pycon

            >>> from spatialmath.base import qconj, qprint
            >>> q = [1, 2, 3, 4]
            >>> qprint(qconj(q))

        :SymPy: supported

    qdot(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], w: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Rate of change of unit-quaternion

        :arg q0: unit-quaternion
        :type q0: array_like(4)
        :arg w: 3D angular velocity in world frame
        :type w: array_like(3)
        :return: rate of change of unit quaternion
        :rtype: ndarray(4)

        ``dot(q, w)`` is the rate of change of the elements of the unit quaternion ``q``
        which represents the orientation of a body frame with angular velocity ``w`` in
        the world frame.

        .. runblock:: pycon

            >>> from spatialmath.base import qdot, qprint
            >>> from math import sqrt
            >>> q = [1/sqrt(2), 1/sqrt(2), 0, 0]   # 90deg rotation about x-axis
            >>> qdot(q, [1, 2, 3])

        .. warning:: There is no check that the passed values are unit-quaternions.

    qdotb(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], w: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Rate of change of unit-quaternion

        :arg q0: unit-quaternion
        :type q0: array_like(4)
        :arg w: 3D angular velocity in body frame
        :type w: array_like(3)
        :return: rate of change of unit quaternion
        :rtype: ndarray(4)

        ``dotb(q, w)`` is the rate of change of the elements of the unit quaternion ``q``
        which represents the orientation of a body frame with angular velocity ``w`` in
        the body frame.

        .. runblock:: pycon

            >>> from spatialmath.base import qdotb, qprint
            >>> from math import sqrt
            >>> q = [1/sqrt(2), 1/sqrt(2), 0, 0]   # 90deg rotation about x-axis
            >>> qdotb(q, [1, 2, 3])

        .. warning:: There is no check that the passed values are unit-quaternions.

    qinner(q1: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], q2: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> float
        Quaternion inner product

        :arg q0: quaternion
        :type q0: : array_like(4)
        :arg q1: uaternion
        :type q1: array_like(4)
        :return: inner product
        :rtype: float

        This is the inner or dot product of two quaternions, it is the sum of the element-wise
        product.

        - The inner product ``inner(q, q)`` is the square of the norm of ``q``.
        - If ``q0`` and ``q1`` are unit quaternions then the inner product is the
          cosine of the angle between the two orientations.

        .. runblock:: pycon

            >>> from spatialmath.base import qinner
            >>> from math import sqrt, acos, pi
            >>> q1 = [1, 2, 3, 4]
            >>> qinner(q1, q1)                     # square of the norm
            >>> q1 = [1/sqrt(2), 1/sqrt(2), 0, 0]  # 90deg rotation about x-axis
            >>> q2 = [1/sqrt(2), 0, 1/sqrt(2), 0]  # 90deg rotation about y-axis
            >>> acos(qinner(q1, q2)) * 180 / pi    # angle between q1 and q2

        :seealso: qvmul

    qisequal(q1, q2, tol: float = 20, unitq: Optional[bool] = False)
        Test if quaternions are equal

        :param q1: quaternion
        :type q1: array_like(4)
        :param q2: quaternion
        :type q2: array_like(4)
        :param unitq: quaternions are unit quaternions
        :type unitq: bool
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether quaternions are equal
        :rtype: bool

        Tests if two quaternions are equal.

        For unit-quaternions ``unitq=True`` the double mapping is taken into account,
        that is ``q`` and ``-q`` represent the same orientation and ``isequal(q, -q, unitq=True)`` will
        return ``True``.

        .. runblock:: pycon

            >>> from spatialmath.base import qisequal
            >>> q1 = [1, 2, 3, 4]
            >>> q2 = [-1, -2, -3, -4]
            >>> qisequal(q1, q2)
            >>> qisequal(q1, q2, unitq=True)

    qisunit(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], tol: float = 20) -> bool
        Test if quaternion has unit length

        :param v: quaternion
        :type v: array_like(4)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: whether quaternion has unit length
        :rtype: bool

        .. runblock:: pycon

            >>> from spatialmath.base import qeye, qpure, qisunit
            >>> q = qeye()
            >>> qisunit(q)
            >>> q = qpure([1, 2, 3])
            >>> qisunit(q)

        :seealso: :func:`qunit`

    qmatrix(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Convert quaternion to 4x4 matrix equivalent

        :arg q: quaternion
        :type v: array_like(4)
        :return: equivalent matrix
        :rtype: ndarray(4)

        Hamilton multiplication between two quaternions can be considered as a
        matrix-vector product, the left-hand quaternion is represented by an
        equivalent 4x4 matrix and the right-hand quaternion as 4x1 column vector.

        .. runblock:: pycon

            >>> from spatialmath.base import qmatrix, qqmul, qprint
            >>> q1 = [1, 2, 3, 4]
            >>> q2 = [5, 6, 7, 8]
            >>> qqmul(q1, q2)    # conventional Hamilton product
            >>> m = qmatrix(q1)
            >>> print(m)
            >>> v = m @ np.array(q2)
            >>> print(v)

        :seealso: qqmul

    qnorm(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> float
        Norm of a quaternion

        :arg q: quaternion
        :type v: : array_like(4)
        :return: norm of the quaternion
        :rtype: float

        Returns the norm (length or magnitude) of the input quaternion which is

        .. math::

            (s^2 + v_x^2 + v_y^2 + v_z^2)^{1/2}

        .. runblock:: pycon

            >>> from spatialmath.base import qnorm
            >>> q = qnorm([1, 2, 3, 4])
            >>> print(q)

        :seealso: :func:`qunit`

    qpow(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], power: int) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Raise quaternion to a power

        :arg q: quaternion
        :type v: array_like(4)
        :arg power: exponent
        :type power: int
        :return: input quaternion raised to the specified power
        :rtype: ndarray(4)
        :raises ValueError: if exponent is non integer

        Raises a quaternion to the specified power using repeated multiplication.

        .. runblock:: pycon

            >>> from spatialmath.base import qpow, qqmul, qprint
            >>> q = [1, 2, 3, 4]
            >>> qprint(qqmul(q, q))
            >>> qprint(qpow(q, 2))
            >>> qprint(qpow(q, -2)) # conjugate of above

        .. note:

            - Power must be an integer
            - Power can be negative, in which case the conjugate is taken

        :seealso: :func:`qqmul`
        :SymPy: supported for ``q`` but not ``power``.

    qprint(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], delim: Optional[Tuple[str, str]] = ('<', '>'), fmt: Optional[str] = '{: .4f}', file: Optional[TextIO] = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'>) -> None
        Format a quaternion to a file

        :arg q: unit-quaternion
        :type q: array_like(4)
        :arg delim: 2-list of delimeters [default ('<', '>')]
        :type delim: list or tuple of strings
        :arg fmt: printf-style format soecifier [default '{: .4f}']
        :type fmt: str
        :arg file: destination for formatted string [default sys.stdout]
        :type file: file object

        Format the quaternion in a human-readable form as::

            S  D1  VX VY VZ D2

        where S, VX, VY, VZ are the quaternion elements, and D1 and D2 are a pair
        of delimeters given by `delim`.

        By default the string is written to `sys.stdout`.

        .. runblock:: pycon

            >>> from spatialmath.base import qprint, qrand
            >>> q = [1, 2, 3, 4]
            >>> qprint(q)
            >>> q = qrand()   # a unit quaternion
            >>> qprint(q, delim=('<<', '>>'))

        :seealso: :meth:`q2str`

    qpure(v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create a pure quaternion

        :arg v: 3D vector
        :type v: array_like(3)
        :return: pure quaternion
        :rtype: ndarray(4)

        Creates a pure quaternion, with a zero scalar value and the vector part
        equal to the passed vector value.

        .. runblock:: pycon

            >>> from spatialmath.base import qpure, qprint
            >>> q = qpure([1, 2, 3])
            >>> qprint(q)

    qqmul(q1: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], q2: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Quaternion multiplication

        :arg q0: left-hand quaternion
        :type q0: : array_like(4)
        :arg q1: right-hand quaternion
        :type q1: array_like(4)
        :return: quaternion product
        :rtype: ndarray(4)

        This is the quaternion or Hamilton product.  If both operands are unit-quaternions then
        the product will be a unit-quaternion.

        .. runblock:: pycon

            >>> from spatialmath.base import qqmul
            >>> q1 = [1, 2, 3, 4]
            >>> q2 = [5, 6, 7, 8]
            >>> qqmul(q1, q2)    # conventional Hamilton product

        :seealso: qvmul, qinner, vvmul

    qrand(theta_range: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None, unit: str = 'rad', num_interpolation_points: int = 256) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Random unit-quaternion

        :arg theta_range: angular magnitude range [min,max], defaults to None.
        :type xrange: 2-element sequence, optional
        :arg unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :arg num_interpolation_points: number of points to use in the interpolation function
        :rtype: int
        :arg num_interpolation_points: number of points to use in the interpolation function
        :rtype: int
        :return: random unit-quaternion
        :rtype: ndarray(4)

        Computes a uniformly distributed random unit-quaternion, with in a maximum
        angular magnitude, which can be considered equivalent to a random SO(3) rotation.

        .. runblock:: pycon

            >>> from spatialmath.base import qrand, qprint
            >>> qprint(qrand())

    qslerp(q0: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], q1: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], s: float, shortest: Optional[bool] = False, tol: float = 20) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Quaternion conjugate

        :arg q0: initial unit quaternion
        :type q0: array_like(4)
        :arg q1: final unit quaternion
        :type q1: array_like(4)
        :arg s: interpolation coefficient in the range [0,1]
        :type s: float
        :arg shortest: choose shortest distance [default False]
        :type shortest: bool
        :param tol: Tolerance when checking for identical quaternions, in multiples of eps, defaults to 20
        :type tol: float, optional
        :return: interpolated unit-quaternion
        :rtype: ndarray(4)
        :raises ValueError: s is outside interval [0, 1]

        An interpolated quaternion between ``q0`` when ``s`` = 0 to ``q1`` when ``s`` = 1.

        Interpolation is performed on a great circle on a 4D hypersphere. This is
        a rotation about a single fixed axis in space which yields the straightest
        and shortest path between two points.

        For large rotations the path may be the *long way around* the circle,
        the option ``'shortest'`` ensures always the shortest path.

        .. runblock:: pycon

            >>> from spatialmath.base import qslerp, qprint
            >>> from math import sqrt
            >>> q0 = [1/sqrt(2), 1/sqrt(2), 0, 0]  # 90deg rotation about x-axis
            >>> q1 = [1/sqrt(2), 0, 1/sqrt(2), 0]  # 90deg rotation about y-axis
            >>> qprint(qslerp(q0, q1, 0))           # this is q0
            >>> qprint(qslerp(q0, q1, 1))           # this is q1
            >>> qprint(qslerp(q0, q1, 0.5))         # this is in "half way" between

        .. warning:: There is no check that the passed values are unit-quaternions.

    qunit(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], tol: float = 20) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create a unit quaternion

        :arg v: quaterion
        :type v: array_like(4)
        :param tol: Tolerance in multiples of eps, defaults to 20
        :type tol: float, optional
        :return: a pure quaternion
        :rtype: ndarray(4)
        :raises ValueError: quaternion has (near) zero norm

        Creates a unit quaternion, with unit norm, by scaling the input quaternion.

        .. runblock:: pycon

            >>> from spatialmath.base import qunit, qprint
            >>> q = qunit([1, 2, 3, 4])
            >>> qprint(q)

        .. note:: Scalar part is always positive.

        .. note:: If the quaternion norm is less than ``tol * eps`` an exception is
                  raised.

        :seealso: :func:`qnorm`

    qvmul(q: Union[List[float], Tuple[float, float, float, float], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Vector rotation

        :arg q: unit-quaternion
        :type q: array_like(4)
        :arg v: 3-vector to be rotated
        :type v: array_like(3)
        :return: rotated 3-vector
        :rtype: ndarray(3)

        The vector `v` is rotated about the origin by the SO(3) equivalent of the unit
        quaternion.

        .. runblock:: pycon

            >>> from spatialmath.base import qvmul
            >>> from math import sqrt
            >>> q = [1/sqrt(2), 1/sqrt(2), 0, 0]  # 90deg rotation about x-axis
            >>> qvmul(q, [1, 2, 3])              # rotated vector

        .. warning:: There is no check that the passed value is a unit-quaternions.

        :seealso: qvmul

    r2q(R: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]], check: Optional[bool] = False, tol: float = 20, order: Optional[str] = 'sxyz', shortest: bool = False) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Convert SO(3) rotation matrix to unit-quaternion

        :arg R: SO(3) rotation matrix
        :type R: ndarray(3,3)
        :param check: check validity of rotation matrix, default False
        :type check: bool
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :param order: the order of the returned quaternion elements. Must be 'sxyz' or
            'xyzs'. Defaults to 'sxyz'.
        :type order: str
        :param shortest: ensures the quaternion has non-negative scalar part.
        :type shortest: bool, default to False
        :return: unit-quaternion as Euler parameters
        :rtype: ndarray(4)
        :raises ValueError: for non SO(3) argument

        Returns a unit-quaternion corresponding to the input SO(3) rotation matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import r2q, qprint, rotx
            >>> R = rotx(90, 'deg') # rotation of 90deg about x-axis
            >>> print(R)
            >>> qprint(r2q(R))

        .. warning:: There is no check that the passed matrix is a valid rotation matrix.

        .. note::
            - Scalar part is always positive
            - implements Cayley's method

        :reference:
            - Sarabandi, S., and Thomas, F. (March 1, 2019).
              "A Survey on the Computation of Quaternions From Rotation Matrices."
              ASME. J. Mechanisms Robotics. April 2019; 11(2): 021006.
              `doi.org/10.1115/1.4041889 <https://doi.org/10.1115/1.4041889>`_

        :seealso: :func:`q2r`

    r2t(R, check=False)
        Convert SO(n) to SE(n)

        :param R: rotation matrix
        :type R: ndarray(2,2) or ndarray(3,3)
        :param check: check if rotation matrix is valid (default False, no check)
        :type check: bool
        :return: homogeneous transformation matrix
        :rtype: ndarray(3,3) or ndarray(4,4)
        :raises ValueError: bad argument

        ``T = r2t(R)`` is an SE(2) or SE(3) homogeneous transform equivalent to an
        SO(2) or SO(3) orthonormal rotation matrix ``R`` with a zero translational
        component

        - if ``R`` is 2x2 then ``T`` is 3x3: SO(2) → SE(2)
        - if ``R`` is 3x3 then ``T`` is 4x4: SO(3) → SE(3)

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> R = rot2(0.3)
            >>> R
            >>> r2t(R)

        :seealso: t2r, rt2tr

    r2x(R: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]], representation: str = 'rpy/xyz') -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert SO(3) matrix to angular representation

        :param R: SO(3) rotation matrix
        :type R: ndarray(3,3)
        :param representation: rotational representation, defaults to "rpy/xyz"
        :type representation: str, optional
        :return: angular representation
        :rtype: ndarray(3)

        Convert an SO(3) rotation matrix to a minimal rotational representation
        :math:`\vec{\Gamma} \in \mathbb{R}^3`.

        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        :SymPy: supported

        :seealso: :func:`x2r` :func:`tr2rpy` :func:`tr2eul` :func:`trlog`

    removesmall(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], tol: float = 20) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Set small values to zero

        :param v: any vector
        :type v: array_like(n) or ndarray(n,m)
        :param tol: Tolerance in units of eps, defaults to 20
        :type tol: int, optional
        :return: vector with small values set to zero
        :rtype: ndarray(n) or ndarray(n,m)

        Values with absolute value less than ``tol`` will be set to zero.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> a = np.r_[1, 2, 3, 1e-16]
            >>> print(a)
            >>> a = removesmall(a)
            >>> print(a)
            >>> print(a[3])

    rodrigues(w: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], theta: Optional[float] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Rodrigues' formula for 3D rotation

        :param w: rotation vector
        :type w: array_like(3)
        :param theta: rotation angle
        :type theta: float or None
        :return: SO(3) matrix
        :rtype: ndarray(3,3)

        Compute Rodrigues' formula for a rotation matrix given a rotation axis
        and angle.

        .. math::

            \mat{R} = \mat{I}_{3 \times 3} + \sin \theta \skx{\hat{\vec{v}}} + (1 - \cos \theta) \skx{\hat{\vec{v}}}^2

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> rodrigues([1, 0, 0], 0.3)
            >>> rodrigues([0.3, 0, 0])

    rot2(theta: float, unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]], numpy.dtype[numpy.floating]]
        Create SO(2) rotation

        :param theta: rotation angle
        :type theta: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: SO(2) rotation matrix
        :rtype: ndarray(2,2)

        - ``rot2(θ)`` is an SO(2) rotation matrix (2x2) representing a rotation of θ radians.
        - ``rot2(θ, 'deg')`` as above but θ is in degrees.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> rot2(0.3)
            >>> rot2(45, 'deg')

    rot2jac(R, representation='rpy/xyz')
        DEPRECATED, use :func:`rotvelxform` instead

    rotvelxform(Γ, inverse=False, full=False, representation='rpy/xyz')
        Rotational velocity transformation

        :param 𝚪: angular representation or rotation matrix
        :type 𝚪: array_like(3) or ndarray(3,3)
        :param representation: defaults to 'rpy/xyz'
        :type representation: str, optional
        :param inverse: compute mapping from analytical rates to angular velocity
        :type inverse: bool
        :param full: return 6x6 transform for spatial velocity
        :type full: bool
        :return: rotation rate transformation matrix
        :rtype: ndarray(3,3) or ndarray(6,6)

        Computes the transformation from analytical rates
        :math:`\dvec{x}` where the rotational part is expressed as the rate of change in
        some angular representation to spatial velocity :math:`\omega`, where
        rotation rate is expressed as angular velocity.

        .. math::
             \vec{\omega} = \mat{A}(\Gamma) \dvec{x}

        where :math:`\mat{A}` is a 3x3 matrix and :math:`\Gamma \in
        \mathbb{R}^3` is a minimal angular representation.

        :math:`\mat{A}(\Gamma)` is a function of the rotational representation
        which can be specified by the parameter ``𝚪`` as a 1D array, or by
        an SO(3) rotation matrix which will be converted to the ``representation``.

        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        If ``inverse==True`` return :math:`\mat{A}^{-1}` computed using
        a closed-form solution rather than matrix inverse.

        If ``full=True`` a block diagonal 6x6 matrix is returned which transforms analytic
        velocity to spatial velocity.

        .. note:: Similar to :func:`eul2jac` :func:`rpy2jac` :func:`exp2jac`
            with ``full=False``.

        The analytical Jacobian is

        .. math::

            \mat{J}_a(q) = \mat{A}^{-1}(\Gamma)\, \mat{J}(q)

        where :math:`\mat{A}` is computed with ``inverse==True`` and ``full=True``.

        Reference:

           - ``symbolic/angvelxform.ipynb`` in this Toolbox
           - Robot Dynamics Lecture Notes, Robotic Systems Lab, ETH Zurich, 2018
             https://ethz.ch/content/dam/ethz/special-interest/mavt/robotics-n-intelligent-systems/rsl-dam/documents/RobotDynamics2018/RD_HS2018script.pdf

        :SymPy: supported

        :seealso: :func:`rotvelxform_inv_dot` :func:`eul2jac` :func:`rpy2r` :func:`exp2jac`

    rotvelxform_inv_dot(Γ: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], Γd: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], full: bool = False, representation: str = 'rpy/xyz') -> Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[6], Literal[6]], numpy.dtype[numpy.floating]]]
        Derivative of angular velocity transformation

        :param 𝚪: angular representation
        :type 𝚪: array_like(3)
        :param 𝚪d: angular representation rate :math:`\dvec{\Gamma}`
        :type 𝚪d: array_like(3)
        :param representation: defaults to 'rpy/xyz'
        :param full: return 6x6 transform for spatial velocity
        :return: derivative of inverse angular velocity transformation matrix
        :rtype: ndarray(6,6) or ndarray(3,3)

        The angular rate transformation matrix :math:`\mat{A} \in \mathbb{R}^{6 \times 6}` is such that

        .. math::

            \dvec{x} = \mat{A}^{-1}(\Gamma) \vec{\nu}

        where :math:`\dvec{x} \in \mathbb{R}^6` is analytic velocity :math:`(\vec{v}, \dvec{\Gamma})`,
        :math:`\vec{\nu} \in \mathbb{R}^6` is spatial velocity :math:`(\vec{v}, \vec{\omega})`, and
        :math:`\vec{\Gamma} \in \mathbb{R}^3` is a minimal rotational
        representation.

        The relationship between spatial and analytic acceleration is

        .. math::

            \ddvec{x} = \dmat{A}^{-1}(\Gamma, \dot{\Gamma}) \vec{\nu} + \mat{A}^{-1}(\Gamma) \dvec{\nu}

        and :math:`\dmat{A}^{-1}(\Gamma, \dot{\Gamma})` is computed by this function.


        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        If ``full=True`` a block diagonal 6x6 matrix is returned which transforms analytic
        analytic rotational acceleration to angular acceleration.

        Reference:

           - ``symbolic/angvelxform.ipynb`` in this Toolbox
           - ``symbolic/angvelxform_dot.ipynb`` in this Toolbox

        :seealso: :func:`rotvelxform` :func:`eul2jac` :func:`rpy2r` :func:`exp2jac`

    rotx(theta: float, unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SO(3) rotation about X-axis

        :param theta: rotation angle about X-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        - ``rotx(θ)`` is an SO(3) rotation matrix (3x3) representing a rotation
          of θ radians about the x-axis
        - ``rotx(θ, "deg")`` as above but θ is in degrees

        .. runblock:: pycon

            >>> from spatialmath.base import rotx
            >>> rotx(0.3)
            >>> rotx(45, 'deg')

        :seealso: :func:`~trotx`
        :SymPy: supported

    roty(theta: float, unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SO(3) rotation about Y-axis

        :param theta: rotation angle about Y-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        - ``roty(θ)`` is an SO(3) rotation matrix (3x3) representing a rotation
          of θ radians about the y-axis
        - ``roty(θ, "deg")`` as above but θ is in degrees

        .. runblock:: pycon

            >>> from spatialmath.base import roty
            >>> roty(0.3)
            >>> roty(45, 'deg')

        :seealso: :func:`~troty`
        :SymPy: supported

    rotz(theta: float, unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SO(3) rotation about Z-axis

        :param theta: rotation angle about Z-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        - ``rotz(θ)`` is an SO(3) rotation matrix (3x3) representing a rotation
          of θ radians about the z-axis
        - ``rotz(θ, "deg")`` as above but θ is in degrees

        .. runblock:: pycon

            >>> from spatialmath.base import rotz
            >>> rotz(0.3)
            >>> rotz(45, 'deg')

        :seealso: :func:`~trotz`
        :SymPy: supported

    rpy2jac(angles: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], order: str = 'zyx') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Jacobian from RPY angle rates to angular velocity

        :param angles: roll-pitch-yaw angles (⍺, β, γ)
        :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
        :return: Jacobian matrix

        - ``rpy2jac(⍺, β, γ)`` is a Jacobian matrix (3x3) that maps roll-pitch-yaw
          angle rates to angular velocity at the operating point (⍺, β, γ). These
          correspond to successive rotations about the axes specified by ``order``:

            - 'zyx' [default], rotate by γ about the z-axis, then by β about the new
              y-axis, then by ⍺ about the new x-axis.  Convention for a mobile robot
              with x-axis forward and y-axis sideways.
            - 'xyz', rotate by γ about the x-axis, then by β about the new y-axis,
              then by ⍺ about the new z-axis. Convention for a robot gripper with
              z-axis forward and y-axis between the gripper fingers.
            - 'yxz', rotate by γ about the y-axis, then by β about the new x-axis,
              then by ⍺ about the new z-axis. Convention for a camera with z-axis
              parallel to the optic axis and x-axis parallel to the pixel rows.

        - ``rpy2jac(𝚪)`` as above but the roll, pitch, yaw angles are taken
          from ``𝚪`` which is a 3-vector with values (⍺, β, γ).

        .. runblock:: pycon

            >>> from spatialmath.base import rpy2jac
            >>> rpy2jac([0.1, 0.2, 0.3])

        .. note::
            - Used in the creation of an analytical Jacobian.
            - Angles in radians, rates in radians/sec.

        :Reference: Robotics, Vision & Control for Python, Section 8.1.3, P. Corke, Springer 2023.

        :SymPy: supported

        :seealso: :func:`rotvelxform` :func:`eul2jac` :func:`exp2jac`

    rpy2r(roll: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], float], pitch: Optional[float] = None, yaw: Optional[float] = None, *, unit: str = 'rad', order: str = 'zyx') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create an SO(3) rotation matrix from roll-pitch-yaw angles

        :param roll: roll angle
        :type roll: float or array_like(3)
        :param pitch: pitch angle
        :type pitch: float
        :param yaw: yaw angle
        :type yaw: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)
        :raises ValueError: bad argument

        - ``rpy2r(⍺, β, γ)`` is an SO(3) orthonormal rotation matrix (3x3)
          equivalent to the specified roll (⍺), pitch (β), yaw (γ) angles angles.
          These correspond to successive rotations about the axes specified by
          ``order``:

            - 'zyx' [default], rotate by γ about the z-axis, then by β about the new
              y-axis, then by ⍺ about the new x-axis.  Convention for a mobile robot
              with x-axis forward and y-axis sideways.
            - 'xyz', rotate by γ about the x-axis, then by β about the new y-axis,
              then by ⍺ about the new z-axis. Convention for a robot gripper with
              z-axis forward and y-axis between the gripper fingers.
            - 'yxz', rotate by γ about the y-axis, then by β about the new x-axis,
              then by ⍺ about the new z-axis. Convention for a camera with z-axis
              parallel to the optic axis and x-axis parallel to the pixel rows.

        - ``rpy2r(RPY)`` as above but the roll, pitch, yaw angles are taken
          from ``RPY`` which is a 3-vector with values (⍺, β, γ).

        .. runblock:: pycon

            >>> from spatialmath.base import rpy2r
            >>> rpy2r(0.1, 0.2, 0.3)
            >>> rpy2r([0.1, 0.2, 0.3])
            >>> rpy2r([10, 20, 30], unit='deg')

        :seealso: :func:`~eul2r` :func:`~rpy2tr` :func:`~tr2rpy`

    rpy2tr(roll, pitch=None, yaw=None, unit: str = 'rad', order: str = 'zyx') -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create an SE(3) rotation matrix from roll-pitch-yaw angles

        :param roll: roll angle
        :type roll: float
        :param pitch: pitch angle
        :type pitch: float
        :param yaw: yaw angle
        :type yaw: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
        :type order: str
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        - ``rpy2tr(⍺, β, γ)`` is an SE(3) matrix (4x4) equivalent to the specified
          roll (⍺), pitch (β), yaw (γ) angles angles. These correspond to successive
          rotations about the axes specified by ``order``:

            - 'zyx' [default], rotate by γ about the z-axis, then by β about the new
              y-axis, then by ⍺ about the new x-axis.  Convention for a mobile robot
              with x-axis forward and y-axis sideways.
            - 'xyz', rotate by γ about the x-axis, then by β about the new y-axis,
              then by ⍺ about the new z-axis. Convention for a robot gripper with
              z-axis forward and y-axis between the gripper fingers.
            - 'yxz', rotate by γ about the y-axis, then by β about the new x-axis,
              then by ⍺ about the new z-axis. Convention for a camera with z-axis
              parallel to the optic axis and x-axis parallel to the pixel rows.

        - ``rpy2tr(RPY)`` as above but the roll, pitch, yaw angles are taken
          from ``RPY`` which is a 3-vector with values (⍺, β, γ).

        .. runblock:: pycon

            >>> from spatialmath.base import rpy2tr
            >>> rpy2tr(0.1, 0.2, 0.3)
            >>> rpy2tr([0.1, 0.2, 0.3])
            >>> rpy2tr([10, 20, 30], unit='deg')

        .. note:: By default, the translational component is zero but it can be
            set to a non-zero value.

        :seealso: :func:`~eul2tr` :func:`~rpy2r` :func:`~tr2rpy`

    rt2tr(R, t, check=False)
        Convert SO(n) and translation to SE(n)

        :param R: SO(n) matrix
        :type R: ndarray(2,2) or ndarray(3,3)
        :param t: translation vector
        :type R: ndarray(2) or ndarray(3)
        :param check: check if SO(3) matrix is valid (default False, no check)
        :type check: bool
        :return: SE(3) matrix
        :rtype: ndarray(4,4) or (3,3)
        :raises ValueError: bad argument

        ``T = rt2tr(R, t)`` is a homogeneous transformation matrix (N+1xN+1) formed from an
        orthonormal rotation matrix ``R`` (NxN) and a translation vector ``t``
        (Nx1).

        - If ``R`` is 2x2 and ``t`` is 2x1, then ``T`` is 3x3
        - If ``R`` is 3x3 and ``t`` is 3x1, then ``T`` is 4x4

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> R = rot2(0.3)
            >>> t = [1, 2]
            >>> rt2tr(R, t)

        :seealso: rt2m, tr2rt, r2t

    skew(v)
        Create skew-symmetric metrix from vector

        :param v: vector
        :type v: array_like(1) or array_like(3)
        :return: skew-symmetric matrix in so(2) or so(3)
        :rtype: ndarray(2,2) or ndarray(3,3)
        :raises ValueError: bad argument

        ``skew(V)`` is a skew-symmetric matrix formed from the elements of ``V``.

        - ``len(V)``  is 1 then ``S`` = :math:`\left[ \begin{array}{cc} 0 & -v \\ v & 0 \end{array} \right]`
        - ``len(V)`` is 3 then ``S`` = :math:`\left[ \begin{array}{ccc} 0 & -v_z & v_y \\ v_z & 0 & -v_x \\ -v_y & v_x & 0\end{array} \right]`

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> skew(2)
            >>> skew([1, 2, 3])

        .. note::

            - This is the inverse of the function ``vex()``.
            - These are the generator matrices for the Lie algebras so(2) and so(3).

        :seealso: :func:`vex` :func:`skewa`
        :SymPy: supported

    skewa(v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], Tuple[float, float, float, float, float, float], numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]]) -> Union[numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]
        Create augmented skew-symmetric metrix from vector

        :param v: vector
        :type v: array_like(3), array_like(6)
        :return: augmented skew-symmetric matrix in se(2) or se(3)
        :rtype: ndarray(3,3) or ndarray(4,4)
        :raises ValueError: bad argument

        ``skewa(V)`` is an augmented skew-symmetric matrix formed from the elements of ``V``.

        - ``len(V)`` is 3 then S = :math:`\left[ \begin{array}{ccc} 0 & -v_3 & v_1 \\ v_3 & 0 & v_2 \\ 0 & 0 & 0 \end{array} \right]`
        - ``len(V)`` is 6 then S = :math:`\left[ \begin{array}{cccc} 0 & -v_6 & v_5 & v_1 \\ v_6 & 0 & -v_4 & v_2 \\ -v_5 & v_4 & 0 & v_3 \\ 0 & 0 & 0 & 0 \end{array} \right]`

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> skewa([1, 2, 3])
            >>> skewa([1, 2, 3, 4, 5, 6])

        .. note::

            - This is the inverse of the function ``vexa()``.
            - These are the generator matrices for the Lie algebras se(2) and se(3).
            - Map twist vectors in 2D and 3D space to se(2) and se(3).

        :seealso: :func:`vexa` :func:`skew`
        :SymPy: supported

    sphere(radius: Optional[float] = 1, centre: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = (0, 0, 0), resolution: Optional[int] = 50) -> Tuple[numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Points on a sphere

        :param centre: centre of sphere, defaults to (0, 0, 0)
        :type centre: array_like(3), optional
        :param radius: radius of sphere, defaults to 1
        :type radius: float, optional
        :param resolution: number of points ``N`` on circumferece, defaults to 50
        :type resolution: int, optional
        :return: X, Y and Z braid matrices
        :rtype: 3 x ndarray(N, N)

        .. note:: By default returns a unit sphere centred at the origin.

        :seealso: :func:`plot_sphere`, :func:`~matplotlib.pyplot.plot_surface`, :func:`~matplotlib.pyplot.plot_wireframe`

    str2array(s: str) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Convert compact single line string to array

        :param s: string to convert
        :type s: str
        :return: array
        :rtype: ndarray

        Convert a string containing a "MATLAB-like" matrix definition to a NumPy
        array.  A scalar has no delimiting square brackets and becomes a 1x1 array.
        A 2D array is delimited by square brackets, elements are separated by a comma,
        and rows are separated by a semicolon.  Extra white spaces are ignored.

        Example:

        .. runblock:: pycon

            >>> from spatialmath.base import str2array
            >>> str2array("5")
            >>> str2array("[1 2 3]")
            >>> str2array("[1 2; 3 4]")
            >>> str2array(" [  1  , 2 ; 3 4  ] ")
            >>> str2array("[1; 2; 3]")

        :seealso: :func:`array2str`

    t2r(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], check: bool = False) -> Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]]
        Convert SE(n) to SO(n)

        :param T: homogeneous transformation matrix
        :type T: ndarray(3,3) or ndarray(4,4)
        :param check: check if rotation matrix is valid (default False, no check)
        :type check: bool
        :return: rotation matrix
        :rtype: ndarray(2,2) or ndarray(3,3)
        :raises ValueError: bad argument

        ``R = T2R(T)`` is the orthonormal rotation matrix component of homogeneous
        transformation matrix ``T``

        - if ``T`` is 3x3 then ``R`` is 2x2: SE(2) → SO(2)
        - if ``T`` is 4x4 then ``R`` is 3x3: SE(3) → SO(3)

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = trot2(0.3, t=[1,2])
            >>> T
            >>> t2r(T)

        .. note:: Any translational component of T is lost.

        :seealso: r2t, tr2rt

    tr2adjoint(T)
        Adjoint matrix

        :param T: SE(3) or SO(3) matrix
        :type T: ndarray(4,4) or ndarray(3,3)
        :return: adjoint matrix
        :rtype: ndarray(6,6) or ndarray(3,3)

        Computes an adjoint matrix that maps the Lie algebra between frames.

        .. math:

            Ad(\mat{T}) \vec{X} X = \vee \left( \mat{T} \skew{\vec{X} \mat{T}^{-1} \right)

        where :math:`\mat{T} \in \SE3`.

        ``tr2jac(T)`` is an adjoint matrix (6x6) that maps spatial velocity or
        differential motion between frame {B} to frame {A} which are attached to the
        same moving body.  The pose of {B} relative to {A} is represented by the
        homogeneous transform T = :math:`{}^A {\bf T}_B`.

        .. runblock:: pycon

            >>> from spatialmath.base import tr2adjoint, trotx
            >>> T = trotx(0.3, t=[4,5,6])
            >>> tr2adjoint(T)

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

        :SymPy: supported

    tr2angvec(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], unit: str = 'rad', check: bool = False) -> Tuple[float, numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]
        Convert SO(3) or SE(3) to angle and rotation vector

        :param R: SE(3) or SO(3) matrix
        :type R: ndarray(4,4) or ndarray(3,3)
        :param unit: 'rad' or 'deg'
        :type unit: str
        :param check: check that rotation matrix is valid
        :type check: bool
        :return: :math:`(\theta, {\bf v})`
        :rtype: float, ndarray(3)
        :raises ValueError: bad arguments

        ``(v, θ) = tr2angvec(R)`` is a rotation angle and a vector about which the
        rotation acts that corresponds to the rotation part of ``R``.

        By default the angle is in radians but can be changed setting `unit='deg'`.

        .. runblock:: pycon

            >>> from spatialmath.base import  troty, tr2angvec
            >>> T = troty(45, 'deg')
            >>> v, theta = tr2angvec(T)
            >>> print(v, theta)

        .. note::

            - If the input is SE(3) the translation component is ignored.

        :seealso: :func:`~angvec2r` :func:`~angvec2tr` :func:`~tr2rpy` :func:`~tr2eul`

    tr2delta(T0: numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]], T1: Optional[numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy.floating]]
        Difference of SE(3) matrices as differential motion

        :param T0: first SE(3) matrix
        :type T0: ndarray(4,4)
        :param T1: second SE(3) matrix
        :type T1: ndarray(4,4)
        :return: Differential motion as a 6-vector
        :rtype: ndarray(6)
        :raises ValueError: bad arguments

        - ``tr2delta(T0, T1)`` is the differential motion Δ (6x1) corresponding to
          infinitessimal motion (in the T0 frame) from pose T0 to T1 which are SE(3)
          matrices.

        - ``tr2delta(T)`` as above but the motion is from the world frame to the
          pose represented by T.

        The vector :math:`\Delta = [\delta_x, \delta_y, \delta_z, \theta_x,
        \theta_y, \theta_z]` represents infinitessimal translation and rotation, and
        is an approximation to the instantaneous spatial velocity multiplied by time
        step.

        .. runblock:: pycon

            >>> from spatialmath.base import tr2delta, trotx
            >>> T1 = trotx(0.3, t=[4,5,6])
            >>> T2 = trotx(0.31, t=[4,5.02,6])
            >>> tr2delta(T1, T2)

        .. note::

            - Δ is only an approximation to the motion T, and assumes
              that T0 ~ T1 or T ~ eye(4,4).
            - Can be considered as an approximation to the effect of spatial velocity over a
              a time interval, average spatial velocity multiplied by time.

        :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.

        :seealso: :func:`~delta2tr`
        :SymPy: supported

    tr2eul(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], unit: str = 'rad', flip: bool = False, check: bool = False, tol: float = 20) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert SO(3) or SE(3) to ZYX Euler angles

        :param R: SE(3) or SO(3) matrix
        :type R: ndarray(4,4) or ndarray(3,3)
        :param unit: 'rad' or 'deg'
        :type unit: str
        :param flip: choose first Euler angle to be in quadrant 2 or 3
        :type flip: bool
        :param check: check that rotation matrix is valid
        :type check: bool
        :param tol: Tolerance in units of eps for near-zero checks, defaults to 20
        :type: float
        :return: ZYZ Euler angles
        :rtype: ndarray(3)

        ``tr2eul(R)`` are the Euler angles corresponding to
        the rotation part of ``R``.

        The 3 angles :math:`[\phi, \theta, \psi]` correspond to sequential rotations
        about the Z, Y and Z axes respectively.

        By default the angles are in radians but can be changed setting `unit='deg'`.

        .. runblock:: pycon

            >>> from spatialmath.base import tr2eul, eul2tr
            >>> T = eul2tr(0.2, 0.3, 0.5)
            >>> print(T)
            >>> tr2eul(T)

        .. note::

            - There is a singularity for the case where :math:`\theta=0` in which
              case we arbitrarily set :math:`\phi = 0` and :math:`\phi` is set to
              :math:`\phi+\psi`.
            - If the input is SE(3) the translation component is ignored.

        :seealso: :func:`~eul2r` :func:`~eul2tr` :func:`~tr2rpy` :func:`~tr2angvec`
        :SymPy: not supported

    tr2jac(T: numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]], numpy.dtype[numpy.floating]]
        SE(3) Jacobian matrix

        :param T: SE(3) matrix
        :type T: ndarray(4,4)
        :return: Jacobian matrix
        :rtype: ndarray(6,6)

        Computes an Jacobian matrix that maps spatial velocity between two frames
        defined by an SE(3) matrix.

        ``tr2jac(T)`` is a Jacobian matrix (6x6) that maps spatial velocity or
        differential motion from frame {B} to frame {A} where the pose of {B}
        elative to {A} is represented by the homogeneous transform T = :math:`{}^A
        {\bf T}_B`.

        .. runblock:: pycon

            >>> from spatialmath.base import tr2jac, trotx
            >>> T = trotx(0.3, t=[4,5,6])
            >>> tr2jac(T)

        :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
        :SymPy: supported

    tr2jac2(T: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        SE(2) Jacobian matrix

        :param T: SE(2) matrix
        :type T: ndarray(3,3)
        :return: Jacobian matrix
        :rtype: ndarray(3,3)

        Computes an Jacobian matrix that maps spatial velocity between two frames defined by
        an SE(2) matrix.

        ``tr2jac2(T)`` is a Jacobian matrix (3x3) that maps spatial velocity or
        differential motion from frame {B} to frame {A} where the pose of {B}
        elative to {A} is represented by the homogeneous transform T = :math:`{}^A {\bf T}_B`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = trot2(0.3, t=[4,5])
            >>> tr2jac2(T)

        :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
        :SymPy: supported

    tr2rpy(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], unit: str = 'rad', order: str = 'zyx', check: bool = False, tol: float = 20) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert SO(3) or SE(3) to roll-pitch-yaw angles

        :param R: SE(3) or SO(3) matrix
        :type R: ndarray(4,4) or ndarray(3,3)
        :param unit: 'rad' or 'deg'
        :type unit: str
        :param order: 'xyz', 'zyx' or 'yxz' [default 'zyx']
        :type order: str
        :param check: check that rotation matrix is valid
        :type check: bool
        :param tol: Tolerance in units of eps, defaults to 20
        :type: float
        :return: Roll-pitch-yaw angles
        :rtype: ndarray(3)
        :raises ValueError: bad arguments

        ``tr2rpy(R)`` are the roll-pitch-yaw angles corresponding to
        the rotation part of ``R``.

        The 3 angles RPY = :math:`[\theta_R, \theta_P, \theta_Y]` correspond to
        sequential rotations about the Z, Y and X axes respectively.  The axis order
        sequence can be changed by setting:

        - ``order='xyz'``  for sequential rotations about X, Y, Z axes
        - ``order='yxz'``  for sequential rotations about Y, X, Z axes

        By default the angles are in radians but can be changed setting
        ``unit='deg'``.

        .. runblock:: pycon

            >>> from spatialmath.base import tr2rpy, rpy2tr
            >>> T = rpy2tr(0.2, 0.3, 0.5)
            >>> print(T)
            >>> tr2rpy(T)

        .. note::

            - There is a singularity for the case where :math:`\theta_P = \pi/2` in
              which case we arbitrarily set :math:`\theta_R=0` and
              :math:`\theta_Y = \theta_R + \theta_Y`.
            - If the input is SE(3) the translation component is ignored.

        :seealso: :func:`~rpy2r` :func:`~rpy2tr` :func:`~tr2eul`,
                  :func:`~tr2angvec`
        :SymPy: not supported

    tr2rt(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], check=False) -> Tuple[Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]], Union[numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]]
        Convert SE(n) to SO(n) and translation

        :param T: SE(n) matrix
        :type T: ndarray(3,3) or ndarray(4,4)
        :param check: check if SO(3) submatrix is valid (default False, no check)
        :type check: bool
        :return: SO(n) matrix and translation vector
        :rtype: tuple: (ndarray(2,2), ndarray(2)) or (ndarray(3,3), ndarray(3))
        :raises ValueError: bad argument

        (R,t) = tr2rt(T) splits a homogeneous transformation matrix (NxN) into an orthonormal
        rotation matrix R (MxM) and a translation vector T (Mx1), where N=M+1.

        - if ``T`` is 3x3 - in SE(2) - then ``R`` is 2x2 and ``t`` is 2x1.
        - if ``T`` is 4x4 - in SE(3) - then ``R`` is 3x3 and ``t`` is 3x1.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = trot2(0.3, t=[1,2])
            >>> T
            >>> R, t = tr2rt(T)
            >>> R
            >>> t

        :seealso: rt2tr, tr2r

    tr2x(T: numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]], representation: str = 'rpy/xyz') -> numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy.floating]]
        Convert SE(3) to an analytic representation

        :param T: pose as an SE(3) matrix
        :type T: ndarray(4,4)
        :param representation: angular representation to use, defaults to "rpy/xyz"
        :type representation: str, optional
        :return: analytic vector representation
        :rtype: ndarray(6)

        Convert an SE(3) matrix into an equivalent vector representation
        :math:`\vec{x}  = (\vec{t},\vec{r}) \in \mathbb{R}^6` where rotation
        :math:`\vec{r} \in \mathbb{R}^3` is encoded in a minimal representation.

        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        :SymPy: supported

        :seealso: :func:`r2x`

    tr2xyt(T: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]], unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert SE(2) to x, y, theta

        :param T: SE(2) matrix
        :type T: ndarray(3,3)
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: [x, y, θ]
        :rtype: ndarray(3)

        - ``tr2xyt(T)`` is a vector giving the equivalent 2D translation and
          rotation for this SO(2) matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = xyt2tr([1, 2, 0.3])
            >>> T
            >>> tr2xyt(T)

        :seealso: trot2

    tranimate(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], **kwargs) -> str
        Animate a 3D coordinate frame

        :param T: SE(3) or SO(3) matrix
        :type T: ndarray(4,4) or ndarray(3,3) or an iterable returning same
        :param nframes: number of steps in the animation [default 100]
        :type nframes: int
        :param repeat: animate in endless loop [default False]
        :type repeat: bool
        :param interval: number of milliseconds between frames [default 50]
        :type interval: int
        :param wait: wait until animation is complete, default False
        :type wait: bool
        :param movie: name of file to write MP4 movie into
        :type movie: str
        :param **kwargs: arguments passed to ``trplot``

        - ``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
          ``nsteps``.

        - ``tranimate(I)`` where ``I`` is an iterable or generator, animates a 3D
          coordinate frame representing the pose of each element in the sequence of
          SO(3) or SE(3) matrices.

        Examples:

                >>> tranimate(transl(1,2,3)@trotx(1), frame='A', arrow=False, dims=[0, 5])
                >>> tranimate(transl(1,2,3)@trotx(1), frame='A', arrow=False, dims=[0, 5], movie='spin.mp4')

        .. note:: For Jupyter this works with the ``notebook`` and ``TkAgg``
            backends.

        .. note:: The animation occurs in the background after ``tranimate`` has
            returned. If ``block=True`` this blocks after the animation has completed.

        .. note:: When saving animation to a file the animation does not appear
            on screen.  A ``StopIteration`` exception may occur, this seems to
            be a matplotlib bug #19599

        :SymPy: not supported

        :seealso: `trplot`, `plotvol3`

    tranimate2(T: Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]], **kwargs)
        Animate a 2D coordinate frame

        :param T: an SE(2) or SO(2) pose to be displayed as coordinate frame
        :type: ndarray(3,3) or ndarray(2,2)
        :param nframes: number of steps in the animation [defaault 100]
        :type nframes: int
        :param repeat: animate in endless loop [default False]
        :type repeat: bool
        :param interval: number of milliseconds between frames [default 50]
        :type interval: int
        :param movie: name of file to write MP4 movie into
        :type movie: str

        Animates a 2D coordinate frame moving from the world frame to a frame represented by the SO(2) or SE(2) matrix to the current axes.

        - If no current figure, one is created
        - If current figure, but no axes, a 3d Axes is created


        Examples:

                tranimate2(transl(1,2)@trot2(1), frame='A', arrow=False, dims=[0, 5])
                tranimate2(transl(1,2)@trot2(1), frame='A', arrow=False, dims=[0, 5], movie='spin.mp4')

    transl(x, y=None, z=None)
        Create SE(3) pure translation, or extract translation from SE(3) matrix

        **Create a translational SE(3) matrix**

        :param x: translation along X-axis
        :type x: float
        :param y: translation along Y-axis
        :type y: float
        :param z: translation along Z-axis
        :type z: float
        :return: SE(3) transformation matrix
        :rtype: numpy(4,4)
        :raises ValueError: bad argument

        - ``T = transl( X, Y, Z )`` is an SE(3) homogeneous transform (4x4)
          representing a pure translation of X, Y and Z.
        - ``T = transl( V )`` as above but the translation is given by a 3-element
          list, dict, or a numpy array, row or column vector.

        .. runblock:: pycon

            >>> from spatialmath.base import transl
            >>> import numpy as np
            >>> transl(3, 4, 5)
            >>> transl([3, 4, 5])
            >>> transl(np.array([3, 4, 5]))

        **Extract the translational part of an SE(3) matrix**

        :param x: SE(3) transformation matrix
        :type x: numpy(4,4)
        :return: translation elements of SE(2) matrix
        :rtype: ndarray(3)
        :raises ValueError: bad argument

        - ``t = transl(T)`` is the translational part of a homogeneous transform T as a
          3-element numpy array.

        .. runblock:: pycon

            >>> from spatialmath.base import transl
            >>> import numpy as np
            >>> T = np.array([[1, 0, 0, 3], [0, 1, 0, 4], [0, 0, 1, 5], [0, 0, 0, 1]])
            >>> transl(T)

        .. 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

    transl2(x, y=None)
        Create SE(2) pure translation, or extract translation from SE(2) matrix

        **Create a translational SE(2) matrix**

        :param x: translation along X-axis
        :type x: float
        :param y: translation along Y-axis
        :type y: float
        :return: SE(2) matrix
        :rtype: ndarray(3,3)

        - ``T = transl2([X, Y])`` is an SE(2) homogeneous transform (3x3)
          representing a pure translation.
        - ``T = transl2( V )`` as above but the translation is given by a 2-element
          list, dict, or a numpy array, row or column vector.


        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> transl2(3, 4)
            >>> transl2([3, 4])
            >>> transl2(np.array([3, 4]))

        **Extract the translational part of an SE(2) matrix**

        :param x: SE(2) transform matrix
        :type x: ndarray(3,3)
        :return: translation elements of SE(2) matrix
        :rtype: ndarray(2)

        - ``t = transl2(T)`` is the translational part of the SE(3) matrix ``T`` as a
          2-element NumPy array.


        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> import numpy as np
            >>> T = np.array([[1, 0, 3], [0, 1, 4], [0, 0, 1]])
            >>> transl2(T)

        .. 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:`tr2pos2` :func:`pos2tr2`

    trexp(S, theta=None, check=True)
        Exponential of se(3) or so(3) matrix

        :param S: se(3), so(3) matrix or equivalent twist vector
        :type T: ndarray(4,4) or ndarray(6); or ndarray(3,3) or ndarray(3)
        :param θ: motion
        :type θ: float
        :return: matrix exponential in SE(3) or SO(3)
        :rtype: ndarray(4,4) or ndarray(3,3)
        :raises ValueError: bad arguments

        An efficient closed-form solution of the matrix exponential for arguments
        that are so(3) or se(3).

        For so(3) the results is an SO(3) rotation matrix:

        - ``trexp(Ω)`` is the matrix exponential of the so(3) element ``Ω`` which is
          a 3x3 skew-symmetric matrix.
        - ``trexp(Ω, θ)`` as above but for an so(3) motion of Ωθ, where ``Ω`` is
          unit-norm skew-symmetric matrix representing a rotation axis and a
          rotation magnitude given by ``θ``.
        - ``trexp(ω)`` is the matrix exponential of the so(3) element ``ω``
          expressed as a 3-vector.
        - ``trexp(ω, θ)`` as above but for an so(3) motion of ωθ where ``ω`` is a
          unit-norm vector representing a rotation axis and a rotation magnitude
          given by ``θ``. ``ω`` is expressed as a 3-vector.

        .. runblock:: pycon

            >>> from spatialmath.base import trexp, skew
            >>> trexp(skew([1, 2, 3]))
            >>> trexp(skew([1, 0, 0]), 2)  # revolute unit twist
            >>> trexp([1, 2, 3])
            >>> trexp([1, 0, 0], 2)  # revolute unit twist

        For se(3) the results is an SE(3) homogeneous transformation matrix:

        - ``trexp(Σ)`` is the matrix exponential of the se(3) element ``Σ`` which is
          a 4x4 augmented skew-symmetric matrix.
        - ``trexp(Σ, θ)`` as above but for an se(3) motion of Σθ, where ``Σ`` must
          represent a unit-twist, ie. the rotational component is a unit-norm
          skew-symmetric matrix.
        - ``trexp(S)`` is the matrix exponential of the se(3) element ``S``
          represented as a 6-vector which can be considered a screw motion.
        - ``trexp(S, θ)`` as above but for an se(3) motion of Sθ, where ``S`` must
          represent a unit-twist, ie. the rotational component is a unit-norm
          skew-symmetric matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import trexp, skewa
            >>> trexp(skewa([1, 2, 3, 4, 5, 6]))
            >>> trexp(skewa([1, 0, 0, 0, 0, 0]), 2)  # prismatic unit twist
            >>> trexp([1, 2, 3, 4, 5, 6])
            >>> trexp([1, 0, 0, 0, 0, 0], 2)

        :seealso: :func:`~trlog :func:`~spatialmath.base.transforms2d.trexp2`

    trexp2(S: Union[numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], theta: Optional[float] = None, check: bool = True) -> Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]]
        Exponential of so(2) or se(2) matrix

        :param S: se(2), so(2) matrix or equivalent vector
        :type T: ndarray(3,3) or ndarray(2,2)
        :param theta: motion
        :type theta: float
        :return: matrix exponential in SE(2) or SO(2)
        :rtype: ndarray(3,3) or ndarray(2,2)
        :raises ValueError: bad argument

        An efficient closed-form solution of the matrix exponential for arguments
        that are se(2) or so(2).

        For se(2) the results is an SE(2) homogeneous transformation matrix:

        - ``trexp2(Σ)`` is the matrix exponential of the se(2) element ``Σ`` which is
          a 3x3 augmented skew-symmetric matrix.
        - ``trexp2(Σ, θ)`` as above but for an se(3) motion of Σθ, where ``Σ``
          must represent a unit-twist, ie. the rotational component is a unit-norm skew-symmetric
          matrix.
        - ``trexp2(S)`` is the matrix exponential of the se(2) element ``S`` represented as
          a 3-vector which can be considered a screw motion.
        - ``trexp2(S, θ)`` as above but for an se(2) motion of Sθ, where ``S``
          must represent a unit-twist, ie. the rotational component is a unit-norm skew-symmetric
          matrix.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> trexp2(skew(1))
            >>> trexp2(skew(1), 2)  # revolute unit twist
            >>> trexp2(1)
            >>> trexp2(1, 2)  # revolute unit twist

        For so(2) the results is an SO(2) rotation matrix:

        - ``trexp2(Ω)`` is the matrix exponential of the so(3) element ``Ω`` which is a 2x2
          skew-symmetric matrix.
        - ``trexp2(Ω, θ)`` as above but for an so(3) motion of Ωθ, where ``Ω`` is
          unit-norm skew-symmetric matrix representing a rotation axis and a rotation magnitude
          given by ``θ``.
        - ``trexp2(ω)`` is the matrix exponential of the so(2) element ``ω`` expressed as
          a 1-vector.
        - ``trexp2(ω, θ)`` as above but for an so(3) motion of ωθ where ``ω`` is a
          unit-norm vector representing a rotation axis and a rotation magnitude
          given by ``θ``. ``ω`` is expressed as a 1-vector.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> trexp2(skewa([1, 2, 3]))
            >>> trexp2(skewa([1, 0, 0]), 2)  # prismatic unit twist
            >>> trexp2([1, 2, 3])
            >>> trexp2([1, 0, 0], 2)

        :seealso: trlog, trexp2

    trinterp(start, end, s, shortest=True)
        Interpolate SE(3) matrices

        :param start: initial SE(3) or SO(3) matrix value when s=0, if None then identity is used
        :type start: ndarray(4,4) or ndarray(3,3)
        :param end: final SE(3) or SO(3) matrix, value when s=1
        :type end: ndarray(4,4) or ndarray(3,3)
        :param s: interpolation coefficient, range 0 to 1
        :type s: float
        :param shortest: take the shortest path along the great circle for the rotation
        :type shortest: bool, default to True
        :return: interpolated SE(3) or SO(3) matrix value
        :rtype: ndarray(4,4) or ndarray(3,3)
        :raises ValueError: bad arguments

        - ``trinterp(None, T, S)`` is a homogeneous transform (4x4) interpolated
          between identity when S=0 and T (4x4) when S=1.
        - ``trinterp(T0, T1, S)`` as above but interpolated
          between T0 (4x4) when S=0 and T1 (4x4) when S=1.
        - ``trinterp(None, R, S)`` is a rotation matrix (3x3) interpolated
          between identity when S=0 and R (3x3) when S=1.
        - ``trinterp(R0, R1, S)`` as above but interpolated
          between R0 (3x3) when S=0 and R1 (3x3) when S=1.

        .. runblock:: pycon

            >>> from spatialmath.base import transl, trinterp
            >>> T1 = transl(1, 2, 3)
            >>> T2 = transl(4, 5, 6)
            >>> trinterp(T1, T2, 0)
            >>> trinterp(T1, T2, 1)
            >>> trinterp(T1, T2, 0.5)
            >>> trinterp(None, T2, 0)
            >>> trinterp(None, T2, 1)
            >>> trinterp(None, T2, 0.5)

        .. note:: Rotation is interpolated using quaternion spherical linear interpolation (slerp).

        :seealso: :func:`spatialmath.base.quaternions.qlerp` :func:`~spatialmath.base.transforms3d.trinterp2`

    trinterp2(start, end, s, shortest: bool = True)
        Interpolate SE(2) or SO(2) matrices

        :param start: initial SE(2) or SO(2) matrix value when s=0, if None then identity is used
        :type start: ndarray(3,3) or ndarray(2,2) or None
        :param end: final SE(2) or SO(2) matrix, value when s=1
        :type end: ndarray(3,3) or ndarray(2,2)
        :param s: interpolation coefficient, range 0 to 1
        :type s: float
        :param shortest: take the shortest path along the great circle for the rotation
        :type shortest: bool, default to True
        :return: interpolated SE(2) or SO(2) matrix value
        :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.

        .. note:: Rotation angle is linearly interpolated.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T1 = transl2(1, 2)
            >>> T2 = transl2(3, 4)
            >>> trinterp2(T1, T2, 0)
            >>> trinterp2(T1, T2, 1)
            >>> trinterp2(T1, T2, 0.5)
            >>> trinterp2(None, T2, 0)
            >>> trinterp2(None, T2, 1)
            >>> trinterp2(None, T2, 0.5)

        :seealso: :func:`~spatialmath.base.transforms3d.trinterp`

    trinv(T: numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Invert an SE(3) matrix

        :param T: SE(3) matrix
        :type T: ndarray(4,4)
        :return: inverse of SE(3) matrix
        :rtype: ndarray(4,4)
        :raises ValueError: bad arguments

        Computes an efficient inverse of an SE(3) matrix:

        :math:`\begin{pmatrix} {\bf R} & t \\ 0\,0\,0 & 1 \end{pmatrix}^{-1} =  \begin{pmatrix} {\bf R}^T & -{\bf R}^T t \\ 0\,0\, 0 & 1 \end{pmatrix}`

        .. runblock:: pycon

            >>> from spatialmath.base import trinv, trotx
            >>> T = trotx(0.3, t=[4,5,6])
            >>> trinv(T)
            >>> T @ trinv(T)

        :SymPy: supported

    trinv2(T: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Invert an SE(2) matrix

        :param T: SE(2) matrix
        :type T: ndarray(3,3)
        :return: inverse of SE(2) matrix
        :rtype: ndarray(3,3)
        :raises ValueError: bad arguments

        Computes an efficient inverse of an SE(2) matrix:

        :math:`\begin{pmatrix} {\bf R} & t \\ 0\,0 & 1 \end{pmatrix}^{-1} =  \begin{pmatrix} {\bf R}^T & -{\bf R}^T t \\ 0\, 0 & 1 \end{pmatrix}`

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = trot2(0.3, t=[4,5])
            >>> trinv2(T)
            >>> T @ trinv2(T)

        :SymPy: supported

    trlog(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], check: bool = True, twist: bool = False, tol: float = 20) -> Union[numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]]
        Logarithm of SO(3) or SE(3) matrix

        :param R: SE(3) or SO(3) matrix
        :type R: ndarray(4,4) or ndarray(3,3)
        :param check: check that matrix is valid
        :type check: bool
        :param twist: return a twist vector instead of matrix [default]
        :type twist: bool
        :param tol: Tolerance in units of eps for zero-rotation case, defaults to 20
        :type: float
        :return: logarithm
        :rtype: ndarray(4,4) or ndarray(3,3)
        :raises ValueError: bad argument

        An efficient closed-form solution of the matrix logarithm for arguments that
        are SO(3) or SE(3).

        - ``trlog(R)`` is the logarithm of the passed rotation matrix ``R`` which
          will be 3x3 skew-symmetric matrix.  The equivalent vector from ``vex()``
          is parallel to rotation axis and its norm is the amount of rotation about
          that axis.
        - ``trlog(T)`` is the logarithm of the passed homogeneous transformation
          matrix ``T`` which will be 4x4 augumented skew-symmetric matrix. The
          equivalent vector from ``vexa()`` is the twist vector (6x1) comprising [v
          w].

        .. runblock:: pycon

            >>> from spatialmath.base import trlog, rotx, trotx
            >>> trlog(trotx(0.3))
            >>> trlog(trotx(0.3), twist=True)
            >>> trlog(rotx(0.3))
            >>> trlog(rotx(0.3), twist=True)

        :seealso: :func:`~trexp` :func:`~spatialmath.base.transformsNd.vex` :func:`~spatialmath.base.transformsNd.vexa`

    trlog2(T: Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]], twist: bool = False, check: bool = True, tol: float = 20) -> Union[float, numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]]]
        Logarithm of SO(2) or SE(2) matrix

        :param T: SE(2) or SO(2) matrix
        :type T: ndarray(3,3) or ndarray(2,2)
        :param check: check that matrix is valid
        :type check: bool
        :param twist: return a twist vector instead of matrix [default]
        :type twist: bool
        :param tol: Tolerance in units of eps for zero-rotation case, defaults to 20
        :type: float
        :return: logarithm
        :rtype: ndarray(3,3) or ndarray(3); or ndarray(2,2) or ndarray(1)
        :raises ValueError: bad argument

        An efficient closed-form solution of the matrix logarithm for arguments that
        are SO(2) or SE(2).

        - ``trlog2(R)`` is the logarithm of the passed rotation matrix ``R`` which
          will be 2x2 skew-symmetric matrix.  The equivalent vector from ``vex()``
          is parallel to rotation axis and its norm is the amount of rotation about
          that axis.
        - ``trlog(T)`` is the logarithm of the passed homogeneous transformation
          matrix ``T`` which will be 3x3 augumented skew-symmetric matrix. The
          equivalent vector from ``vexa()`` is the twist vector (6x1) comprising [v
          w].

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> trlog2(trot2(0.3))
            >>> trlog2(trot2(0.3), twist=True)
            >>> trlog2(rot2(0.3))
            >>> trlog2(rot2(0.3), twist=True)

        :seealso: :func:`~trexp`, :func:`~spatialmath.base.transformsNd.vex`,
                  :func:`~spatialmath.base.transformsNd.vexa`

    trnorm(T: numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Normalize an SO(3) or SE(3) matrix

        :param T: SE(3) or SO(3) matrix
        :type T: ndarray(4,4) or ndarray(3,3)
        :return: normalized SE(3) or SO(3) matrix
        :rtype: ndarray(4,4) or ndarray(3,3)
        :raises ValueError: bad arguments

        - ``trnorm(R)`` is guaranteed to be a proper orthogonal matrix rotation
          matrix (3x3) which is *close* to the input matrix R (3x3).
        - ``trnorm(T)`` as above but the rotational submatrix of the homogeneous
          transformation T (4x4) is normalised while the translational part is
          unchanged.

        The steps in normalization are:

        #. If :math:`\mathbf{R} = [n, o, a]`
        #. Form unit vectors :math:`\hat{o}, \hat{a}` from  :math:`o, a` respectively
        #. Form the normal vector :math:`\hat{n} = \hat{o} \times \hat{a}`
        #. Recompute :math:`\hat{o} = \hat{a} \times \hat{n}` to ensure that :math:`\hat{o}, \hat{a}` are orthogonal
        #. Form the normalized SO(3) matrix :math:`\mathbf{R} = [\hat{n}, \hat{o}, \hat{a}]`

        .. runblock:: pycon

            >>> from spatialmath.base import trnorm, troty
            >>> from numpy import linalg
            >>> T = troty(45, 'deg', t=[3, 4, 5])
            >>> linalg.det(T[:3,:3]) - 1 # is a valid SO(3)
            >>> T = T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T
            >>> linalg.det(T[:3,:3]) - 1  # not quite a valid SE(3) anymore
            >>> T = trnorm(T)
            >>> linalg.det(T[:3,:3]) - 1  # once more a valid SE(3)

        .. note::

            - Only the direction of a-vector (the z-axis) is unchanged.
            - Used to prevent finite word length arithmetic causing transforms to
              become 'unnormalized', ie. determinant :math:`\ne 1`.

    trnorm2(T: numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Normalize an SO(2) or SE(2) matrix

        :param T: SE(2) or SO(2) matrix
        :type T: ndarray(3,3) or ndarray(2,2)
        :return: normalized SE(2) or SO(2) matrix
        :rtype: ndarray(3,3) or ndarray(2,2)
        :raises ValueError: bad arguments

        - ``trnorm(R)`` is guaranteed to be a proper orthogonal matrix rotation
          matrix (2,2) which is *close* to the input matrix R (2,2).
        - ``trnorm(T)`` as above but the rotational submatrix of the homogeneous
          transformation T (3,3) is normalised while the translational part is
          unchanged.

        The steps in normalization are:

        #. If :math:`\mathbf{R} = [a, 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 numpy import linalg
            >>> T = trot2(45, 'deg', t=[3, 4])
            >>> linalg.det(T[:2,:2]) - 1 # is a valid SO(3)
            >>> T = T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T @ T
            >>> linalg.det(T[:2,:2]) - 1  # not quite a valid SE(2) anymore
            >>> T = trnorm2(T)
            >>> linalg.det(T[:2,:2]) - 1  # once more a valid SE(2)

        .. note::

            - Only the direction of a-vector (the z-axis) is unchanged.
            - Used to prevent finite word length arithmetic causing transforms to
              become 'unnormalized', ie. determinant :math:`\ne 1`.

    trot2(theta: float, unit: str = 'rad', t: Union[List[float], Tuple[float, float], numpy.ndarray[Tuple[Literal[2]], numpy.dtype[numpy.floating]], NoneType] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SE(2) pure rotation

        :param theta: rotation angle about X-axis
        :type θ: float
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :param t: 2D translation vector, defaults to [0,0]
        :type t: array_like(2)
        :return: 3x3 homogeneous transformation matrix
        :rtype: ndarray(3,3)

        - ``trot2(θ)`` is a homogeneous transformation (3x3) representing a rotation of
          θ radians.
        - ``trot2(θ, 'deg')`` as above but θ is in degrees.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> trot2(0.3)
            >>> trot2(45, 'deg', t=[1,2])

        .. note:: By default, the translational component is zero but it can be
            set to a non-zero value.

        :seealso: xyt2tr

    trotx(theta: float, unit: str = 'rad', t: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create SE(3) pure rotation about X-axis

        :param theta: rotation angle about X-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :param t: 3D translation vector, defaults to [0,0,0]
        :type t: array_like(3)
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        - ``trotx(θ)`` is a homogeneous transformation (4x4) representing a rotation
          of θ radians about the x-axis.
        - ``trotx(θ, 'deg')`` as above but θ is in degrees
        - ``trotx(θ, 'rad', t=[x,y,z])`` as above with translation of [x,y,z]

        .. runblock:: pycon

            >>> from spatialmath.base import trotx
            >>> trotx(0.3)
            >>> trotx(45, 'deg', t=[1,2,3])

        :seealso: :func:`~rotx`
        :SymPy: supported

    troty(theta: float, unit: str = 'rad', t: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create SE(3) pure rotation about Y-axis

        :param theta: rotation angle about Y-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :param t: 3D translation vector, defaults to [0,0,0]
        :type t: array_like(3)
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        - ``troty(θ)`` is a homogeneous transformation (4x4) representing a rotation
          of θ radians about the y-axis.
        - ``troty(θ, 'deg')`` as above but θ is in degrees
        - ``troty(θ, 'rad', t=[x,y,z])`` as above with translation of [x,y,z]

        .. runblock:: pycon

            >>> from spatialmath.base import troty
            >>> troty(0.3)
            >>> troty(45, 'deg', t=[1,2,3])

        :seealso: :func:`~roty`
        :SymPy: supported

    trotz(theta: float, unit: str = 'rad', t: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None) -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Create SE(3) pure rotation about Z-axis

        :param theta: rotation angle about Z-axis
        :param unit: angular units: 'rad' [default], or 'deg'
        :param t: 3D translation vector, defaults to [0,0,0]
        :type t: array_like(3)
        :return: SE(3) transformation matrix
        :rtype: ndarray(4,4)

        - ``trotz(θ)`` is a homogeneous transformation (4x4) representing a rotation
          of θ radians about the z-axis.
        - ``trotz(θ, 'deg')`` as above but θ is in degrees
        - ``trotz(θ, 'rad', t=[x,y,z])`` as above with translation of [x,y,z]

        .. runblock:: pycon

            >>> from spatialmath.base import trotz
            >>> trotz(0.3)
            >>> trotz(45, 'deg', t=[1,2,3])

        :seealso: :func:`~rotz`
        :SymPy: supported

    trplot(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], style: str = 'arrow', color: Union[str, Tuple[str, str, str], List[str]] = 'blue', frame: str = '', axislabel: bool = True, axissubscript: bool = True, textcolor: str = '', labels: Tuple[str, str, str] = ('X', 'Y', 'Z'), length: float = 1, originsize: float = 20, origincolor: str = '', projection: str = 'ortho', block: Optional[bool] = None, anaglyph: Union[bool, str, Tuple[str, float], NoneType] = None, wtl: float = 0.2, width: Optional[float] = None, ax: Optional[mpl_toolkits.mplot3d.axes3d.Axes3D] = None, dims: Union[List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]], NoneType] = None, d2: float = 1.15, flo: Tuple[float, float, float] = (-0.05, -0.05, -0.05), **kwargs)
        Plot a 3D coordinate frame

        :param T: SE(3) or SO(3) matrix
        :type T: ndarray(4,4) or ndarray(3,3) or an iterable returning same
        :param style: axis style: 'arrow' [default], 'line', 'rgb', 'rviz' (Rviz style)
        :type style: str
        :param color: color of the lines defining the frame
        :type color: str or list(3) or tuple(3) of str
        :param textcolor: color of text labels for the frame, default ``color``
        :type textcolor: str
        :param frame: label the frame, name is shown below the frame and as subscripts on the frame axis labels
        :type frame: str
        :param axislabel: display labels on axes, default True
        :type axislabel: bool
        :param axissubscript: display subscripts on axis labels, default True
        :type axissubscript: bool
        :param labels: labels for the axes, defaults to X, Y and Z
        :type labels: 3-tuple of strings
        :param length: length of coordinate frame axes, default 1
        :type length: float or array_like(3)
        :param originsize: size of dot to draw at the origin, 0 for no dot (default 20)
        :type originsize: int
        :param origincolor: color of dot to draw at the origin, default is ``color``
        :type origincolor: str
        :param ax: the axes to plot into, defaults to current axes
        :type ax: Axes3D reference
        :param block: run the GUI main loop until all windows are closed, default True
        :type block: bool
        :param dims: dimension of plot volume as [xmin, xmax, ymin, ymax,zmin, zmax].
            If dims is [min, max] those limits are applied to the x-, y- and z-axes.
        :type dims: array_like(6) or array_like(2)
        :param anaglyph: 3D anaglyph display, if True use use red-cyan glasses.  To
            set the color pass a string like ``'gb'`` for green-blue glasses. To set the
            disparity (default 0.1) provide second argument in a tuple, eg. ``('rc', 0.2)``.
            Bigger disparity exagerates the 3D "pop out" effect.
        :type anaglyph: bool, str or (str, float)
        :param wtl: width-to-length ratio for arrows, default 0.2
        :type wtl: float
        :param projection: 3D projection: ortho [default] or persp
        :type projection: str
        :param width: width of lines, default 1
        :type width: float
        :param flo: frame label offset, a vector for frame label text string relative
            to frame origin, default (-0.05, -0.05, -0.05)
        :type flo: array_like(3)
        :param d2: distance of frame axis label text from origin, default 1.15
        :type d2: float
        :return: axes containing the frame
        :rtype: Axes3DSubplot
        :raises ValueError: bad arguments

        Adds a 3D coordinate frame represented by the SO(3) or SE(3) matrix to the
        current axes. If ``T`` is iterable then multiple frames will be drawn.

        The appearance of the coordinate frame depends on many parameters:

        - coordinate axes depend on:
            - ``color`` of axes
            - ``width`` of line
            - ``length`` of line
            - ``style`` which is one of:

                - ``'arrow'`` [default], draw line with arrow head in ``color``
                - ``'line'``, draw line with no arrow head in ``color``
                - ``'rgb'``, frame axes are lines with no arrow head and red for X, green
                  for Y, blue for Z; no origin dot
                - ``'rviz'``, frame axes are thick lines with no arrow head and red for X,
                  green for Y, blue for Z; no origin dot

        - coordinate axis labels depend on:

            - ``axislabel`` if True [default] label the axis, default labels are X, Y, Z
            - ``labels`` 3-list of alternative axis labels
            - ``textcolor`` which defaults to ``color``
            - ``axissubscript`` if True [default] add the frame label ``frame`` as a subscript
              for each axis label

        - coordinate frame label depends on:

            - `frame` the label placed inside {} near the origin of the frame

        - a dot at the origin

            - ``originsize`` size of the dot, if zero no dot
            - ``origincolor`` color of the dot, defaults to ``color``

        Examples::

            trplot(T, frame='A')
            trplot(T, frame='A', color='green')
            trplot(T1, 'labels', 'UVW');

        .. plot::

            import matplotlib.pyplot as plt
            from spatialmath.base import trplot, transl, rpy2tr
            fig = plt.figure(figsize=(10,10))
            text_opts = dict(bbox=dict(boxstyle="round",
                fc="w",
                alpha=0.9),
                zorder=20,
                family='monospace',
                fontsize=8,
                verticalalignment='top')
            T = transl(2, 1, 1)@ rpy2tr(0, 0, 0)

            ax = fig.add_subplot(331, projection='3d')
            trplot(T, ax=ax, dims=[0,4])
            ax.text(0.5, 0.5, 4.5, "trplot(T)", **text_opts)
            ax = fig.add_subplot(332, projection='3d')
            trplot(T, ax=ax, dims=[0,4], originsize=0)
            ax.text(0.5, 0.5, 4.5, "trplot(T, originsize=0)", **text_opts)
            ax = fig.add_subplot(333, projection='3d')
            trplot(T, ax=ax, dims=[0,4], style='line')
            ax.text(0.5, 0.5, 4.5, "trplot(T, style='line')", **text_opts)
            ax = fig.add_subplot(334, projection='3d')
            trplot(T, ax=ax, dims=[0,4], axislabel=False)
            ax.text(0.5, 0.5, 4.5, "trplot(T, axislabel=False)", **text_opts)
            ax = fig.add_subplot(335, projection='3d')
            trplot(T, ax=ax, dims=[0,4], width=3)
            ax.text(0.5, 0.5, 4.5, "trplot(T, width=3)", **text_opts)
            ax = fig.add_subplot(336, projection='3d')
            trplot(T, ax=ax, dims=[0,4], frame='B')
            ax.text(0.5, 0.5, 4.5, "trplot(T, frame='B')", **text_opts)
            ax = fig.add_subplot(337, projection='3d')
            trplot(T, ax=ax, dims=[0,4], color='r', textcolor='k')
            ax.text(0.5, 0.5, 4.5, "trplot(T, color='r', textcolor='k')", **text_opts)
            ax = fig.add_subplot(338, projection='3d')
            trplot(T, ax=ax, dims=[0,4], labels=("u", "v", "w"))
            ax.text(0.5, 0.5, 4.5, "trplot(T, labels=('u', 'v', 'w'))", **text_opts)
            ax = fig.add_subplot(339, projection='3d')
            trplot(T, ax=ax, dims=[0,4], style='rviz')
            ax.text(0.5, 0.5, 4.5, "trplot(T, style='rviz')", **text_opts)


        .. note:: If ``axes`` is specified the plot is drawn there, otherwise:
            - it will draw in the current figure (as given by ``gca()``)
            - if no axes in the current figure, it will create a 3D axes
            - if no current figure, it will create one, and a 3D axes

        .. note:: ``width`` can be set in the ``rgb`` or ``rviz`` styles to override the
            defaults which are 1 and 8 respectively.

        .. note:: The ``anaglyph`` effect is induced by drawing two versions of the
            frame in different colors: one that corresponds to lens over the left
            eye and one to the lens over the right eye. The view for the right eye
            is from a view point shifted in the positive x-direction.

        .. note:: The origin is normally indicated with a marker of the same color
            as the frame.  The default size is 20. This can be disabled by setting
            its size to zero by ``originsize=0``.  For ``'rgb'`` style the default is 0
            but it can be set explicitly, and the color is as per the ``color``
            option.

        :SymPy: not supported

        :seealso: :func:`tranimate` :func:`plotvol3` :func:`axes_logic`

    trplot2(T: Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]], color: str = 'blue', frame: Optional[str] = None, axislabel: bool = True, axissubscript: bool = True, textcolor: Union[str, List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], NoneType] = None, labels: Tuple[str, str] = ('X', 'Y'), length: float = 1, arrow: bool = True, originsize: float = 20, rviz: bool = False, ax: Optional[matplotlib.axes._axes.Axes] = None, block: Optional[bool] = None, dims: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]], NoneType] = None, wtl: float = 0.2, width: float = 1, d1: float = 0.1, d2: float = 1.15, **kwargs)
        Plot a 2D coordinate frame

        :param T: an SE(3) or SO(3) pose to be displayed as coordinate frame
        :type: ndarray(3,3) or ndarray(2,2)
        :param color: color of the lines defining the frame
        :type color: str
        :param textcolor: color of text labels for the frame, default color of lines above
        :type textcolor: str
        :param frame: label the frame, name is shown below the frame and as subscripts on the frame axis labels
        :type frame: str
        :param axislabel: display labels on axes, default True
        :type axislabel: bool
        :param axissubscript: display subscripts on axis labels, default True
        :type axissubscript: bool
        :param labels: labels for the axes, defaults to X and Y
        :type labels: 2-tuple of strings
        :param length: length of coordinate frame axes, default 1
        :type length: float
        :param arrow: show arrow heads, default True
        :type arrow: bool
        :param ax: the axes to plot into, defaults to current axes
        :type ax: Axes3D reference
        :param block: run the GUI main loop until all windows are closed, default None
        :type block: bool
        :param dims: dimension of plot volume as [xmin, xmax, ymin, ymax]
        :type dims: array_like(4)
        :param wtl: width-to-length ratio for arrows, default 0.2
        :type wtl: float
        :param rviz: show Rviz style arrows, default False
        :type rviz: bool
        :param width: width of lines, default 1
        :type width: float
        :param d1: distance of frame axis label text from origin, default 0.05
        :type d1: float
        :param d2: distance of frame label text from origin, default 1.15
        :type d2: float
        :return: axes containing the frame
        :rtype: AxesSubplot
        :raises ValueError: bad argument

        Adds a 2D coordinate frame represented by the SO(2) or SE(2) matrix to the current axes.

        The appearance of the coordinate frame depends on many parameters:

        - coordinate axes depend on:

            - ``color`` of axes
            - ``width`` of line
            - ``length`` of line
            - ``arrow`` if True [default] draw the axis with an arrow head

        - coordinate axis labels depend on:

            - ``axislabel`` if True [default] label the axis, default labels are X, Y, Z
            - ``labels`` 2-list of alternative axis labels
            - ``textcolor`` which defaults to ``color``
            - ``axissubscript`` if True [default] add the frame label ``frame`` as a subscript
            for each axis label

        - coordinate frame label depends on:

            - `frame` the label placed inside {...} near the origin of the frame

        - a dot at the origin

            - ``originsize`` size of the dot, if zero no dot
            - ``origincolor`` color of the dot, defaults to ``color``
            - If no current figure, one is created
            - If current figure, but no axes, a 3d Axes is created

        Examples::

            trplot2(T, frame='A')
            trplot2(T, frame='A', color='green')
            trplot2(T1, 'labels', 'AB');

        .. plot::

            import matplotlib.pyplot as plt
            from spatialmath.base import trplot2, transl2, trot2
            import math
            fig, ax = plt.subplots(3,3, figsize=(10,10))
            text_opts = dict(bbox=dict(boxstyle="round",
                fc="w",
                alpha=0.9),
                zorder=20,
                family='monospace',
                fontsize=8,
                verticalalignment='top')
            T = transl2(2, 1)@trot2(math.pi/3)
            trplot2(T, ax=ax[0][0], dims=[0,4,0,4])
            ax[0][0].text(0.2, 3.8, "trplot2(T)", **text_opts)
            trplot2(T, ax=ax[0][1], dims=[0,4,0,4], originsize=0)
            ax[0][1].text(0.2, 3.8, "trplot2(T, originsize=0)", **text_opts)
            trplot2(T, ax=ax[0][2], dims=[0,4,0,4], arrow=False)
            ax[0][2].text(0.2, 3.8, "trplot2(T, arrow=False)", **text_opts)
            trplot2(T, ax=ax[1][0], dims=[0,4,0,4], axislabel=False)
            ax[1][0].text(0.2, 3.8, "trplot2(T, axislabel=False)", **text_opts)
            trplot2(T, ax=ax[1][1], dims=[0,4,0,4], width=3)
            ax[1][1].text(0.2, 3.8, "trplot2(T, width=3)", **text_opts)
            trplot2(T, ax=ax[1][2], dims=[0,4,0,4], frame='B')
            ax[1][2].text(0.2, 3.8, "trplot2(T, frame='B')", **text_opts)
            trplot2(T, ax=ax[2][0], dims=[0,4,0,4], color='r', textcolor='k')
            ax[2][0].text(0.2, 3.8, "trplot2(T, color='r',textcolor='k')", **text_opts)
            trplot2(T, ax=ax[2][1], dims=[0,4,0,4], labels=("u", "v"))
            ax[2][1].text(0.2, 3.8, "trplot2(T, labels=('u', 'v'))", **text_opts)
            trplot2(T, ax=ax[2][2], dims=[0,4,0,4], rviz=True)
            ax[2][2].text(0.2, 3.8, "trplot2(T, rviz=True)", **text_opts)


        :SymPy: not supported

        :seealso: :func:`tranimate2` :func:`plotvol2` :func:`axes_logic`

    trprint(T: Union[numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4], Literal[4]], numpy.dtype[numpy.floating]]], orient: str = 'rpy/zyx', label: str = '', file: <class 'TextIO'> = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'>, fmt: str = '{:.3g}', degsym: bool = True, unit: str = 'deg') -> str
         Compact display of SO(3) or SE(3) matrices

         :param T: SE(3) or SO(3) matrix
         :type T: ndarray(4,4) or ndarray(3,3)
         :param label: text label to put at start of line
         :type label: str
         :param orient: 3-angle convention to use
         :type orient: str
         :param file: file to write formatted string to. [default, stdout]
         :type file: file object
         :param fmt: conversion format for each number in the format used with ``format``
         :type fmt: str
         :param unit: angular units: 'rad' [default], or 'deg'
         :type unit: str
         :return: formatted string
         :rtype: str
         :raises ValueError: bad argument

         The matrix is formatted and written to ``file`` and the
         string is returned.  To suppress writing to a file, set ``file=None``.

        - ``trprint(R)`` prints the SO(3) rotation matrix to stdout in a compact
           single-line format:

             [LABEL:] ORIENTATION UNIT

         - ``trprint(T)`` prints the SE(3) homogoneous transform to stdout in a
           compact single-line format:

             [LABEL:] [t=X, Y, Z;] ORIENTATION UNIT

         - ``trprint(X, file=None)`` as above but returns the string rather than
           printing to a file

         Orientation is expressed in one of several formats:

         - 'rpy/zyx' roll-pitch-yaw angles in ZYX axis order [default]
         - 'rpy/yxz' roll-pitch-yaw angles in YXZ axis order
         - 'rpy/zyx' roll-pitch-yaw angles in ZYX axis order
         - 'eul' Euler angles in ZYZ axis order
         - 'angvec' angle and axis


         .. runblock:: pycon

             >>> from spatialmath.base import transl, rpy2tr, trprint
             >>> T = transl(1,2,3) @ rpy2tr(10, 20, 30, 'deg')
             >>> trprint(T, file=None)
             >>> trprint(T, file=None, label='T', orient='angvec')
             >>> trprint(T, file=None, label='T', orient='angvec', fmt='{:8.4g}')

         .. note::

             - If the 'rpy' option is selected, then the particular angle sequence can be
               specified with the options 'xyz' or 'yxz' which are passed through to ``tr2rpy``.
               'zyx' is the default.
             - Default formatting is for compact display of data
             - For tabular data set ``fmt`` to a fixed width format such as
               ``fmt='{:.3g}'``

         :seealso: :func:`~spatialmath.base.transforms2d.trprint2` :func:`~tr2eul` :func:`~tr2rpy` :func:`~tr2angvec`
         :SymPy: not supported

    trprint2(T: Union[numpy.ndarray[Tuple[Literal[2], Literal[2]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[3], Literal[3]], numpy.dtype[numpy.floating]]], label: str = '', file: <class 'TextIO'> = <_io.TextIOWrapper name='<stdout>' mode='w' encoding='cp1252'>, fmt: str = '{:.3g}', unit: str = 'deg') -> str
        Compact display of SE(2) or SO(2) matrices

        :param T: matrix to format
        :type T: ndarray(3,3) or ndarray(2,2)
        :param label: text label to put at start of line
        :type label: str
        :param file: file to write formatted string to
        :type file: file object
        :param fmt: conversion format for each number
        :type fmt: str
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: formatted string
        :rtype: str

        The matrix is formatted and written to ``file`` and the
        string is returned.  To suppress writing to a file, set ``file=None``.

        - ``trprint2(R)`` displays the SO(2) rotation matrix in a compact
          single-line format and returns the string::

            [LABEL:] θ UNIT

        - ``trprint2(T)`` displays the SE(2) homogoneous transform in a compact
          single-line format and returns the string::

            [LABEL:] [t=X, Y;] θ UNIT

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> T = transl2(1,2) @ trot2(0.3)
            >>> trprint2(T, file=None, label='T')
            >>> trprint2(T, file=None, label='T', fmt='{:8.4g}')


        .. note::

            - Default formatting is for compact display of data
            - For tabular data set ``fmt`` to a fixed width format such as
              ``fmt='{:.3g}'``

        :seealso: trprint

    unittwist(S: Union[List[float], Tuple[float, float, float, float, float, float], numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]], tol: float = 20) -> Optional[numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]]
        Convert twist to unit twist

        :param S: twist vector
        :type S: array_like(6)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: unit twist
        :rtype: ndarray(6)

        A unit twist is a twist where:

        - the rotation part has unit magnitude
        - if the rotational part is zero, then the translational part has unit magnitude

        .. runblock:: pycon

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

        Returns None if the twist has zero magnitude

    unittwist2(S: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], tol: float = 20) -> Optional[numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]
        Convert twist to unit twist

        :param S: twist vector
        :type S: array_like(3)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: unit twist
        :rtype: ndarray(3)

        A unit twist is a twist where:

        - the rotation part has unit magnitude
        - if the rotational part is zero, then the translational part has unit magnitude

        .. runblock:: pycon

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

        .. note:: Returns None if the twist has zero magnitude

    unittwist_norm(S: Union[numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]], List[float], Tuple[float, float, float, float, float, float]], tol: float = 20) -> Tuple[Optional[numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]], Optional[float]]
        Convert twist to unit twist and norm

        :param S: twist vector
        :type S: array_like(6)
        :param tol: tolerance in units of eps, defaults to 20
        :type tol: float
        :return: unit twist and scalar motion
        :rtype: tuple (ndarray(6), float)

        A unit twist is a twist where:

        - the rotation part has unit magnitude
        - if the rotational part is zero, then the translational part has unit magnitude

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> S, n = unittwist_norm([1, 2, 3, 1, 0, 0])
            >>> print(S, n)
            >>> S, n = unittwist_norm([0, 0, 0, 2, 0, 0])
            >>> print(S, n)
            >>> S, n = unittwist_norm([0, 0, 0, 0, 0, 0])
            >>> print(S, n)

        .. note:: Returns (None,None) if the twist has zero magnitude

    unitvec(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], tol: float = 20) -> numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
        Create a unit vector

        :param v: any vector
        :type v: array_like(n)
        :param tol: Tolerance in units of eps for zero-norm case, defaults to 20
        :type: float
        :return: a unit-vector parallel to ``v``.
        :rtype: ndarray(n)
        :raises ValueError: for zero length vector

        ``unitvec(v)`` is a vector parallel to `v` of unit length.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> unitvec([3, 4])

        :seealso: :func:`~numpy.linalg.norm`

    unitvec_norm(v: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]], tol: float = 20) -> Tuple[numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]], float]
        Create a unit vector

        :param v: any vector
        :type v: array_like(n)
        :param tol: Tolerance in units of eps for zero-norm case, defaults to 20
        :type: float
        :return: a unit-vector parallel to ``v`` and the norm
        :rtype: (ndarray(n), float)
        :raises ValueError: for zero length vector

        ``unitvec(v)`` is a vector parallel to `v` of unit length.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> unitvec([3, 4])

        :seealso: :func:`~numpy.linalg.norm`

    v2q(v: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy.floating]]
        Convert 3-vector to unit-quaternion

        :arg v: vector part of unit quaternion
        :type v: array_like(3)
        :return: a unit quaternion
        :rtype: ndarray(4)

        Returns a unit-quaternion reconsituted from just its vector part.  Assumes
        that the scalar part was positive, so :math:`s = \sqrt{1-||v||}`.

        .. runblock:: pycon

            >>> from spatialmath.base import v2q, qprint
            >>> from math import sqrt
            >>> v = [0, 1 / sqrt(2), 0]
            >>> qprint(v2q(v))
            >>> v = [0, -1 / sqrt(2), 0]
            >>> qprint(v2q(v))

        .. warning:: There is no check that the value is the vector part of
                     a unit-quaternion, and this can lead to a math domain error.

        :seealso: :func:`q2v`

    vex(s, check=False)
        Convert skew-symmetric matrix to vector

        :param s: skew-symmetric matrix
        :type s: ndarray(2,2) or ndarray(3,3)
        :param check: check if matrix is skew symmetric (default False, no check)
        :type check: bool
        :return: vector of unique values
        :rtype: ndarray(1) or ndarray(3)
        :raises ValueError: bad argument

        ``vex(S)`` is the vector which has the corresponding skew-symmetric matrix ``S``.

        - ``S`` is 2x2 - so(2) case - where ``S`` :math:`= \left[ \begin{array}{cc} 0 & -v \\ v & 0 \end{array} \right]` then return :math:`[v]`
        - ``S`` is 3x3 - so(3) case -  where ``S`` :math:`= \left[ \begin{array}{ccc} 0 & -v_z & v_y \\ v_z & 0 & -v_x \\ -v_y & v_x & 0\end{array} \right]` then return :math:`[v_x, v_y, v_z]`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> S = skew(2)
            >>> print(S)
            >>> vex(S)
            >>> S = skew([1, 2, 3])
            >>> print(S)
            >>> vex(S)

        .. note::

            - This is the inverse of the function ``skew()``.
            - Only rudimentary checking (zero diagonal) is done to ensure that the matrix
              is actually skew-symmetric.
            - The function takes the mean of the two elements that correspond to each unique
              element of the matrix.

        :seealso: :func:`skew` :func:`vexa`
        :SymPy: supported

    vexa(Omega: Union[numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[4]], numpy.dtype[numpy.floating]]], check: bool = False) -> Union[numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]], numpy.ndarray[Tuple[Literal[6]], numpy.dtype[numpy.floating]]]
        Convert skew-symmetric matrix to vector

        :param s: augmented skew-symmetric matrix
        :type s: ndarray(3,3) or ndarray(4,4)
        :param check: check if matrix is skew symmetric part is valid (default False, no check)
        :type check: bool
        :return: vector of unique values
        :rtype: ndarray(3) or ndarray(6)
        :raises ValueError: bad argument

        ``vexa(S)`` is the vector which has the corresponding augmented skew-symmetric matrix ``S``.

        - ``S`` is 3x3 - se(2) case - where ``S`` :math:`= \left[ \begin{array}{ccc} 0 & -v_3 & v_1 \\ v_3 & 0 & v_2 \\ 0 & 0 & 0 \end{array} \right]` then return :math:`[v_1, v_2, v_3]`.
        - ``S`` is 4x4 - se(3) case -  where ``S`` :math:`= \left[ \begin{array}{cccc} 0 & -v_6 & v_5 & v_1 \\ v_6 & 0 & -v_4 & v_2 \\ -v_5 & v_4 & 0 & v_3 \\ 0 & 0 & 0 & 0 \end{array} \right]` then return :math:`[v_1, v_2, v_3, v_4, v_5, v_6]`.

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> S = skewa([1, 2, 3])
            >>> print(S)
            >>> vexa(S)
            >>> S = skewa([1, 2, 3, 4, 5, 6])
            >>> print(S)
            >>> vexa(S)

        .. note::

            - This is the inverse of the function ``skewa``.
            - Only rudimentary checking (zero diagonal) is done to ensure that the matrix
              is actually skew-symmetric.
            - The function takes the mean of the two elements that correspond to each unique
              element of the matrix.

        :seealso: :func:`skewa` :func:`vex`
        :SymPy: supported

    vvmul(qa: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], qb: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]]) -> numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy.floating]]
        Quaternion multiplication

        :arg qa: left-hand quaternion
        :type qa: : array_like(3)
        :arg qb: right-hand quaternion
        :type qb: array_like(3)
        :return: quaternion product
        :rtype: ndarray(3)

        This is the quaternion or Hamilton product of unit-quaternions defined only
        by their vector components.  The product will be a unit-quaternion, defined only
        by its vector component.

        .. runblock:: pycon

            >>> from spatialmath.base import vvmul, v2q, q2v, qqmul, qprint
            >>> from math import sqrt
            >>> q1 = [1/sqrt(2), 1/sqrt(2), 0, 0]  # 90deg rotation about x-axis
            >>> q2 = [1/sqrt(2), 0, 1/sqrt(2), 0]  # 90deg rotation about y-axis
            >>> qprint(qqmul(q1, q2))              # normal Hamilton product
            >>> v1 = q2v(q1); v2 = q2v(q2)
            >>> vp = vvmul(v1, v2)                 # product using 3-vectors
            >>> qprint(v2q(vp))                    # same answer as Hamilton product

        :seealso: :func:`q2v` :func:`v2q` :func:`qvmul`

    wrap_0_2pi(theta: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> Union[float, numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Wrap angle to range :math:`[0, 2\pi)`

        :param theta: input angle
        :type theta: scalar or ndarray
        :return: angle wrapped into range :math:`[0, 2\pi)`
        :rtype: scalar or ndarray

        :seealso: :func:`wrap_mpi_pi` :func:`wrap_0_pi` :func:`wrap_mpi2_pi2` :func:`angle_wrap`

    wrap_0_pi(theta: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> Union[float, numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Wrap angle to range :math:`[0, \pi]`

        :param theta: input angle
        :type theta: scalar or ndarray
        :return: angle wrapped into range :math:`[0, \pi)`
        :rtype: scalar or ndarray

        This is used to fold angles of colatitude.  If zero is the angle of the
        north pole, colatitude increases to :math:`\pi` at the south pole then
        decreases to :math:`0` as we head back to the north pole.

        :seealso: :func:`wrap_mpi2_pi2` :func:`wrap_0_2pi` :func:`wrap_mpi_pi` :func:`angle_wrap`

    wrap_mpi_pi(theta: Union[float, List[float], Tuple[float, ...], numpy.ndarray[Any, numpy.dtype[numpy.floating]]]) -> Union[float, numpy.ndarray[Any, numpy.dtype[+_ScalarType_co]]]
        Wrap angle to range :math:`[-\pi, \pi)`

        :param theta: input angle
        :type theta: scalar or ndarray
        :return: angle wrapped into range :math:`[-\pi, \pi)`
        :rtype: scalar or ndarray

        :seealso: :func:`wrap_0_2pi` :func:`wrap_0_pi` :func:`wrap_mpi2_pi2` :func:`angle_wrap`

    x2r(r: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], representation: str = 'rpy/xyz') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Convert angular representation to SO(3) matrix

        :param r: angular representation
        :type r: array_like(3)
        :param representation: rotational representation, defaults to "rpy/xyz"
        :type representation: str, optional
        :return: SO(3) rotation matrix
        :rtype: ndarray(3,3)

        Convert a minimal rotational representation :math:`\vec{\Gamma} \in
        \mathbb{R}^3` to an SO(3) rotation matrix.

        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        :SymPy: supported

        :seealso: :func:`r2x` :func:`rpy2r` :func:`eul2r` :func:`trexp`

    x2tr(x: numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy.floating]], representation='rpy/xyz') -> numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]], numpy.dtype[numpy.floating]]
        Convert analytic representation to SE(3)

        :param x: analytic vector representation
        :type x: array_like(6)
        :param representation: angular representation to use, defaults to "rpy/xyz"
        :type representation: str, optional
        :return: pose as an SE(3) matrix
        :rtype: ndarray(4,4)

        Convert a vector representation of pose :math:`\vec{x} = (\vec{t},\vec{r})
        \in \mathbb{R}^6` to SE(3), where rotation :math:`\vec{r} \in \mathbb{R}^3` is encoded
        in a minimal representation to an equivalent SE(3) matrix.

        ============================  ========================================
        ``representation``            Rotational representation
        ============================  ========================================
        ``"rpy/xyz"`` ``"arm"``       RPY angular rates in XYZ order (default)
        ``"rpy/zyx"`` ``"vehicle"``   RPY angular rates in XYZ order
        ``"rpy/yxz"`` ``"camera"``    RPY angular rates in YXZ order
        ``"eul"``                     Euler angular rates in ZYZ order
        ``"exp"``                     exponential coordinate rates
        ============================  ========================================

        :SymPy: supported

        :seealso: :func:`r2x`

    xyt2tr(xyt: Union[List[float], Tuple[float, float, float], numpy.ndarray[Tuple[Literal[3]], numpy.dtype[numpy.floating]]], unit: str = 'rad') -> numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]], numpy.dtype[numpy.floating]]
        Create SE(2) pure rotation

        :param xyt: 2d translation and rotation
        :type xyt: array_like(3)
        :param unit: angular units: 'rad' [default], or 'deg'
        :type unit: str
        :return: SE(2) matrix
        :rtype: ndarray(3,3)

        - ``xyt2tr([x,y,θ])`` is a homogeneous transformation (3x3) representing a rotation of
          θ radians and a translation of (x,y).

        .. runblock:: pycon

            >>> from spatialmath.base import *
            >>> xyt2tr([1,2,0.3])
            >>> xyt2tr([1,2,45], 'deg')

        :seealso: tr2xyt

DATA
    __all__ = ['assertmatrix', 'ismatrix', 'getvector', 'assertvector', 'i...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\base\__init__.py

spatialmath-python.baseposelist
Python Library Documentation: module spatialmath.baseposelist in spatialmath

NAME
    spatialmath.baseposelist - Provide list super powers for spatial math objects.

CLASSES
    abc.ABC(builtins.object)
        BasePoseList(collections.UserList, abc.ABC)
    collections.UserList(collections.abc.MutableSequence)
        BasePoseList(collections.UserList, abc.ABC)

    class BasePoseList(collections.UserList, abc.ABC)
     |  BasePoseList(initlist=None)
     |
     |  List properties for spatial math classes
     |
     |  Each of the spatial math classes behaves like a regular Python object and
     |  an instance contains a value of a particular type, for example an SE(3)
     |  matrix, a unit quaternion, a twist etc.
     |
     |  This class adds list-like capabilities to each of spatial math classes.  This
     |  means that an instance is not limited to holding just a single value (a
     |  singleton instance), it can hold a list of values.  That list can contain
     |  zero or more items.  This is helpful for:
     |
     |  - storing sequences (trajectories) where it is important to know that all
     |    elements in the sequence are of the same time and have valid values
     |  - arrays of the same type to enable C++ like programming patterns
     |
     |  This class inherits from ``collections.UserList`` and wraps those list-like
     |  methods in spatial math specific ways.  The list operations supported are:
     |
     |  ==================  ============================================================
     |  syntax              meaning
     |  ==================  ============================================================
     |  ``C()``             create a singleton instance of ``C`` with the identity value
     |  ``C.Empty()``       create an instance of ``C`` with zero items
     |  ``C.Alloc(n)``      create an instance of ``C`` with ``n`` identity items
     |  ``len(x)``          return the number of items in ``x``
     |  ``x[i]``            return the ``i``'th item of ``x``, ``i`` is an index
     |                      or a slice.
     |  ``x[i] = y``        set the ``i``'th item of ``x`` to the singleton instance
     |                      ``y`` and ``i`` is an index
     |  ``x.append(y)``     append the value of singleton instance ``y`` to ``x``
     |  ``x.extend(y)``     append the items of ``y`` to ``x``
     |  ``x.pop()``         pop the first item of ``x``
     |  ``x.insert(i, y)``  insert the value of singleton instsance ``y`` into ``x``
     |                      at position ``i``.
     |  ``del x[i]``        delete the ``i``'th element of ``x``
     |  ``x.reverse()``     reverse the elements of ``x`` in place
     |  ``x.clear()``       remove all items from ``x``
     |  ==================  ============================================================
     |
     |  where ``C`` is the class, and ``x`` and ``y`` are instances of ``C``.
     |
     |  Notes:
     |
     |  - The subclass must invoke ``super().__init__()``
     |  - ``UserList`` keeps the list in the ``.data`` attribute
     |  - Some list method do not make sense for spatial math, these are:
     |    ``count``, ``remove`` and ``sort``.
     |
     |  Method resolution order:
     |      BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x, check=True)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  shape
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'_identity', 'isvalid', 'shape'})
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __init__(self, initlist=None)
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  __repr__(self)
     |      Return repr(self).
     |
     |  __rmul__ = __mul__(self, n)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike4 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike6 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLikePure = typing.Union[typing.List[float], typing.Tuple[fl...nda...
    Callable = typing.Callable
        Deprecated alias to collections.abc.Callable.

        Callable[[int], str] signifies a function that takes a single
        parameter of type int and returns a str.

        The subscription syntax must always be used with exactly two
        values: the argument list and the return type.
        The argument list must be a list of types, a ParamSpec,
        Concatenate or ellipsis. The return type must be a single type.

        There is no syntax to indicate optional or keyword arguments;
        such function types are rarely used as callback types.

    Color = typing.Union[str, typing.List[float], typing.Tup...typing.Lite...
    DTypeLike = typing.Union[numpy.dtype[typing.Any], NoneType, ...e_like....
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    L = typing.Literal
        Special typing form to define literal types (a.k.a. value types).

        This form can be used to indicate to type checkers that the corresponding
        variable or function parameter has a value equivalent to the provided
        literal (or one of several literals)::

            def validate_simple(data: Any) -> Literal[True]:  # always returns True
                ...

            MODE = Literal['r', 'rb', 'w', 'wb']
            def open_helper(file: str, mode: MODE) -> str:
                ...

            open_helper('/some/path', 'r')  # Passes type check
            open_helper('/other/path', 'typo')  # Error in type checker

        Literal[...] cannot be subclassed. At runtime, an arbitrary value
        is allowed as type argument to Literal[...], but type checkers may
        impose restrictions.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Points3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    QuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy...
    R1 = numpy.ndarray[typing.Tuple[typing.Literal[1]], numpy.dtype[numpy....
    R1x1 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[1]...
    R1x2 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[2]...
    R1x3 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[3]...
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R2x1 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[1]...
    R2x2 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]...
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R3x1 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[1]...
    R3x3 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]...
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    R4x4 = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]...
    R6 = numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy....
    R6x6 = numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]...
    R8 = numpy.ndarray[typing.Tuple[typing.Literal[8]], numpy.dtype[numpy....
    R8x8 = numpy.ndarray[typing.Tuple[typing.Literal[8], typing.Literal[8]...
    RNx3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Rn = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.Literal...
    SE2Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SE3Array = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Litera...
    SEnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    SO2Array = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Litera...
    SO3Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SOnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Type = typing.Type
        Deprecated alias to builtins.type.

        builtins.type or typing.Type can be used to annotate class objects.
        For example, suppose we have the following classes::

            class User: ...  # Abstract base for User classes
            class BasicUser(User): ...
            class ProUser(User): ...
            class TeamUser(User): ...

        And a function that takes a class argument that's a subclass of
        User and returns an instance of the corresponding class::

            def new_user[U](user_class: Type[U]) -> U:
                user = user_class()
                # (Here we could write the user object to a database)
                return user

            joe = new_user(BasicUser)

        At this point the type checker knows that joe has type BasicUser.

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

    UnitQuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], n...
    se2Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    se3Array = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[...
    senArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    so2Array = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[...
    so3Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    sonArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\baseposelist.py

spatialmath-python.baseposematrix
Python Library Documentation: module spatialmath.baseposematrix in spatialmath

NAME
    spatialmath.baseposematrix

DESCRIPTION
    # Part of Spatial Math Toolbox for Python
    # Copyright (c) 2000 Peter Corke
    # MIT Licence, see details in top-level file: LICENCE

CLASSES
    spatialmath.baseposelist.BasePoseList(collections.UserList, abc.ABC)
        BasePoseMatrix

    class BasePoseMatrix(spatialmath.baseposelist.BasePoseList)
     |  BasePoseMatrix(*args, **kwargs)
     |
     |  Superclass for SO(N) and SE(N) objects
     |
     |  Subclasses are:
     |
     |  - ``SO2`` representing elements of SO(2) which describe rotations in 2D
     |  - ``SE2`` representing elements of SE(2) which describe rigid-body motion in 2D
     |  - ``SO3`` representing elements of SO(3) which describe rotations in 3D
     |  - ``SE3`` representing elements of SE(3) which describe rigid-body motion in 3D
     |
     |  Arithmetic operators are overloaded but the operation they perform depend
     |  on the types of the operands.  For example:
     |
     |  - ``*`` will compose two instances of the same subclass, and the result will
     |    be an instance of the same subclass, since this is a group operator.
     |  - ``+`` will add two instances of the same subclass, and the result will be
     |    a matrix, not an instance of the same subclass, since addition is not a group operator.
     |
     |  These classes all inherit from ``UserList`` which enables them to
     |  represent a sequence of values, ie. an ``SE3`` instance can contain
     |  a sequence of SE(3) values.  Most of the Python ``list`` operators
     |  are applicable::
     |
     |      >>> x = SE3()  # new instance with identity matrix value
     |      >>> len(x)     # it is a sequence of one value
     |      1
     |      >>> x.append(x)  # append to itself
     |      >>> len(x)       # it is a sequence of two values
     |      2
     |      >>> x[1]         # the element has a 4x4 matrix value
     |      SE3([
     |      array([[1., 0., 0., 0.],
     |             [0., 1., 0., 0.],
     |             [0., 0., 1., 0.],
     |          [0., 0., 0., 1.]]) ])
     |      >>> x[1] = SE3.Rx(0.3)  # set an elements of the sequence
     |      >>> x.reverse()         # reverse the elements in the sequence
     |      >>> del x[1]            # delete an element
     |
     |  For console printing colorization is supported if the package ``colored``
     |  is installed.  Class variables control the colorization and can be assigned
     |  to at any time.
     |
     |  ===============  ===================  ============================================
     |  Variable         Default              Description
     |  ===============  ===================  ============================================
     |  _rotcolor        'red'                Foreground color of rotation submatrix
     |  _transcolor      'blue'               Foreground color of rotation submatrix
     |  _constcolor      'grey_50'            Foreground color of matrix constant elements
     |  _bgcolor         None                 Background color of matrix
     |  _indexcolor      (None, 'yellow_2')   Foreground, background color of index tag
     |  _format          '{:< 12g}'           Format string for each matrix element
     |  _suppress_small  True                 Suppress *small* values, set to zero
     |  _suppress_tol    100                  Threshold for *small* values in eps units
     |  _ansimatrix      False                Display with matrix brackets
     |  ===============  ===================  ============================================
     |
     |  If color is specified as ``None`` it means no colorization is performed.
     |
     |  For example::
     |
     |      >> SE3._bgcolor = None
     |      >> SE3._indexcolor = ('green', None)
     |
     |  .. note:: The ``_ansimatrix`` option requires that the ``ansitable`` package
     |      is installed.  It does not currently support colorization of elements.
     |
     |  Method resolution order:
     |      BasePoseMatrix
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __add__(left, right)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Add the elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
     |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
     |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ========================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ========================
     |      Pose             Pose             NxN matrix   element-wise matrix sum
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ========================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar + Pose is handled by :meth:`__radd__`
     |          #. Addition is commutative
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose addition either or both operands may hold more than one value which
     |      results in the sum holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``sum = left + right``
     |       1          M             M    ``sum[i] = left + right[i]``
     |       N          1             M    ``sum[i] = left[i] + right``
     |       M          M             M    ``sum[i] = left[i] + right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __eq__(left, right: 'Self') -> 'bool'
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for equality
     |
     |      ``X == Y`` is true of the poses are of the same type and numerically
     |      equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the equality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``eq = left == right``
     |       1          M             M    ``eq[i] = left == right[i]``
     |       N          1             M    ``eq[i] = left[i] == right``
     |       M          M             M    ``eq[i] = left[i] == right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __iadd__(left, right)
     |      Overloaded ``+=`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
     |      - ``X += s`` elementwise addition of the matrix elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__add__``
     |
     |  __imul__(left, right)
     |      Overloaded ``*=`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
     |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__mul__``
     |
     |  __isub__(left, right: 'Self')
     |      Overloaded ``-=`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises: ValueError
     |
     |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
     |        and ``Y`` and places the result in ``X``
     |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
     |        and the scalar ``s`` and places the result in ``X``
     |
     |      :seealso: ``__sub__``
     |
     |  __itruediv__(left, right)
     |      Overloaded ``/=`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
     |      - ``X /= s`` performs elementwise division of the elements of ``X``
     |        by ``s`` and places the result in ``X``
     |
     |      :seealso: ``__truediv__``
     |
     |  __matmul__(left, right)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :return: Product of two operands with normalization
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
     |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
     |        and places the result in ``X``
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally
     |          update over many cycles.
     |
     |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Pose composition, scaling or vector transformation:
     |
     |      - ``X * Y`` compounds the poses ``X`` and ``Y``
     |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
     |
     |      ==============   ==============   ===========  ======================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ======================
     |      Pose             Pose             Pose         matrix product
     |      Pose             scalar           NxN matrix   element-wise product
     |      scalar           Pose             NxN matrix   element-wise product
     |      Pose             N-vector         N-vector     vector transform
     |      Pose             NxM matrix       NxM matrix   transform each column
     |      ==============   ==============   ===========  ======================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar x Pose is handled by __rmul__`
     |          #. Scalar multiplication is commutative but the result is not a group
     |             operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
     |          SE3(array([[0., 0., 1., 0.],
     |                  [1., 0., 0., 0.],
     |                  [0., 1., 0., 0.],
     |                  [0., 0., 0., 1.]]))
     |          >>> SE3.Rx(pi/2) * 2
     |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
     |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
     |
     |      For vector transformation there are three cases:
     |
     |      =========  ===========  =====  ==========================
     |            Multiplicands             Product
     |      ----------------------  ---------------------------------
     |      len(left)  right.shape  shape  operation
     |      =========  ===========  =====  ==========================
     |      1          (N,)         (N,)   vector transformation
     |      M          (N,)         (N,M)  vector transformations
     |      1          (N,M)        (N,M)  column transformation
     |      =========  ===========  =====  ==========================
     |
     |      .. note::
     |          - The vector is an array-like, a 1D NumPy array or a list/tuple
     |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
     |            form, transformed, then converted back to Euclidean form.
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * [0, 1, 0]
     |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
     |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
     |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :return: Inequality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for inequality
     |
     |      - ``X != Y`` is true of the poses are of the same type but not numerically
     |        equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the inequality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``ne = left != right``
     |       1          M             M    ``ne[i] = left != right[i]``
     |       N          1             M    ``ne[i] = left[i] != right``
     |       M          M             M    ``ne[i] = left[i] != right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __pow__(self, n: 'int') -> 'Self'
     |      Overloaded ``**`` operator (superclass method)
     |
     |      :param n: exponent
     |      :type n: int
     |      :return: pose to the power ``n``
     |      :rtype: pose instance
     |
     |      ``X**n`` raise all values held in `X` to the specified power using repeated
     |      multiplication.  If ``n`` < 0 then the result is inverted.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.1) ** 2
     |          >>> SE3.Rx([0, 0.1]) ** 2
     |
     |  __radd__(right, left)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__add__`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> repr(x)
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Left-multiplication
     |
     |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
     |        elements of ``X`` by ``s`` and the result is a NumPy array.
     |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
     |        of ``A`` and ``X`` and the result is a NumPy array.
     |
     |      :seealso: :func:`__mul__`
     |
     |  __rsub__(right, left: 'Self')
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__sub__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of pose (superclass method)
     |
     |      :return: readable representation of the pose
     |      :rtype: str
     |
     |      Convert the pose's matrix value to a simple grid of numbers.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x)
     |
     |      Notes:
     |
     |          - By default, the output is colorised for an ANSI terminal console:
     |
     |              * red: rotational elements
     |              * blue: translational elements
     |              * white: constant elements
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Subtract elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
     |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
     |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ==============================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ==============================
     |      Pose             Pose             NxN matrix   element-wise matrix difference
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ==============================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar - Pose is handled by :meth:`__rsub__`
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose subtraction either or both operands may hold more than one value which
     |      results in the difference holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``diff = left - right``
     |       1          M             M    ``diff[i] = left - right[i]``
     |       N          1             M    ``diff[i] = left[i] - right``
     |       M          M             M    ``diff[i] = left[i]  right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __truediv__(left, right)
     |      Overloaded ``/`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      Pose composition or scaling:
     |
     |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
     |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
     |
     |      ==============   ==============   ===========  =========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   --------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  =========================
     |      Pose             Pose             Pose         matrix product by inverse
     |      Pose             scalar           NxN matrix   element-wise division
     |      ==============   ==============   ===========  =========================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar multiplication is not a group operation so the result will
     |             be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |  animate(self, *args, start=None, **kwargs) -> 'None'
     |      Plot pose object as an animated coordinate frame (superclass method)
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: same as ``self``
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
     |        from the origin in either 2D or 3D.  There are many options, see the
     |        links below.
     |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
     |        frame moving from pose ``X1``, in either 2D or 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=SE3.Ry(0.2))
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
     |
     |  conjugation(self, A: 'NDArray') -> 'NDArray'
     |      Matrix conjugation
     |
     |      :param A: matrix to conjugate
     |      :type A: ndarray
     |      :return: conjugated matrix
     |      :rtype: ndarray
     |
     |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
     |      is the current object.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO2
     |          >>> import numpy as np
     |          >>> R = SO2(0.5)
     |          >>> A = np.array([[10, 0], [0, 1]])
     |          >>> print(R * A * R.inv())
     |          >>> print(R.conjugation(A))
     |
     |  det(self) -> 'Tuple[float, Rn]'
     |      Determinant of rotational component (superclass method)
     |
     |      :return: Determinant of rotational component
     |      :rtype: float or NumPy array
     |
     |      ``x.det()`` is the determinant of the rotation component of the values
     |      of ``x``.
     |
     |      Example::
     |
     |          >>> x=SE3.Rand()
     |          >>> x.det()
     |          1.0000000000000004
     |          >>> x=SE3.Rand(N=2)
     |          >>> x.det()
     |          [0.9999999999999997, 1.0000000000000002]
     |
     |      :SymPy: not supported
     |
     |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
     |      Interpolate between poses (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :param shortest: take the shortest path along the great circle for the rotation
     |      :type shortest: bool, default to True
     |      :return: interpolated pose
     |      :rtype: same as ``self``
     |
     |      - ``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.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
     |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
     |          >>> x.interp(y, 0)    # this is x
     |          >>> x.interp(y, 1)    # this is y
     |          >>> x.interp(y, 0.5)  # this is in between
     |          >>> z = x.interp(y, 11)  # in 11 steps
     |          >>> len(z)
     |          >>> z[0]              # this is x
     |          >>> z[5]              # this is in between
     |
     |      .. note::
     |
     |          - 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
     |
     |  interp1(self, s: 'float' = None) -> 'Self'
     |      Interpolate pose (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1
     |      :type s: array_like
     |      :return: interpolated pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
     |
     |          ======  ======  ===========  ===============================
     |          len(X)  len(s)  len(result)  Result
     |          ======  ======  ===========  ===============================
     |          1       1       1            Y = interp(X, s)
     |          M       1       M            Y[i] = interp(X[i], s)
     |          1       M       M            Y[i] = interp(X, s[i])
     |          ======  ======  ===========  ===============================
     |
     |      Example::
     |
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x.interp(0))
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |          >>> print(x.interp(1))
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
     |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |          >>> y = x.interp(x, np.linspace(0, 1, 10))
     |          >>> len(y)
     |          10
     |          >>> y[5]
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
     |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |
     |      Notes:
     |
     |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
     |
     |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
     |
     |      :SymPy: not supported
     |
     |  ishom(self) -> 'bool'
     |      Test if object belongs to SE(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          True
     |
     |  ishom2(self) -> 'bool'
     |      Test if object belongs to SE(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          True
     |
     |  isrot(self) -> 'bool'
     |      Test if object belongs to SO(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          False
     |
     |  isrot2(self) -> 'bool'
     |      Test if object belongs to SO(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          False
     |
     |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
     |      Logarithm of pose (superclass method)
     |
     |      :return: logarithm
     |      :rtype: ndarray
     |      :raises: ValueError
     |
     |      An efficient closed-form solution of the matrix logarithm.
     |
     |      =====  ======  ===============================
     |      Input         Output
     |      -----  ---------------------------------------
     |      Pose   Shape   Structure
     |      =====  ======  ===============================
     |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
     |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
     |      =====  ======  ===============================
     |
     |      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. ]])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
     |      :func:`~spatialmath.base.transforms3d.trlog`
     |
     |      :SymPy: not supported
     |
     |  norm(self) -> 'Self'
     |      Normalize pose (superclass method)
     |
     |      :return: pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
     |        part of all values has been adjusted to ensure it is a proper orthogonal
     |        matrix rotation.
     |
     |      Example::
     |
     |          >>> x = SE3()
     |          >>> y = x.norm()
     |          >>> y
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |
     |      Notes:
     |
     |      #. Only the direction of A vector (the z-axis) is unchanged.
     |      #. Used to prevent finite word length arithmetic causing transforms to
     |         become 'unnormalized'.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
     |
     |  plot(self, *args, **kwargs) -> 'None'
     |      Plot pose object as a coordinate frame (superclass method)
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
     |        2D or 3D.  There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.plot(frame='A', color='green')
     |
     |      .. plot::
     |
     |          from spatialmath import SE3
     |          X = SE3.Rx(0.3)
     |          X.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
     |
     |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
     |      Print pose as a matrix (superclass method)
     |
     |      :param label: label to print before the matrix, defaults to None
     |      :type label: str, optional
     |      :param file: file to write to, defaults to None
     |      :type file: file object, optional
     |
     |      Print the pose as a matrix, with an optional line beforehand.  By default
     |      the matrix is printed to stdout.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3().print()
     |          >>> SE3().print("pose is:")
     |
     |      :seealso: :meth:`printline` :meth:`strline`
     |
     |  printline(self, *args, **kwargs) -> 'None'
     |      Print pose in compact single line format (superclass method)
     |
     |      :param arg: value for orient option, optional
     |      :type arg: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param file: file to write formatted string to. [default, stdout]
     |      :type file: file object
     |
     |      Print pose in a compact single line format. If ``X`` has multiple
     |      values, print one per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.printline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.printline()
     |          >>> x.printline('angvec')
     |          >>> x.printline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.printline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
     |
     |  prod(self, norm=False, check=True) -> 'Self'
     |      Product of elements (superclass method)
     |
     |      :param norm: normalize the product, defaults to False
     |      :type norm: bool, optional
     |      :param check: check that computed matrix is valid member of group, default True
     |      :bool check: bool, optional
     |      :return: Product of elements
     |      :rtype: pose instance
     |
     |      ``x.prod()`` is the product of the values held by ``x``, ie.
     |      :math:`\prod_i^N T_i`.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
     |          >>> x.prod()
     |
     |      .. note:: When compounding many transformations the product may become
     |          denormalized resulting in a result that is not a proper member of the
     |          group.  You can either disable membership checking by ``check=False``
     |          which is risky, or normalize the result by ``norm=True``.
     |
     |  simplify(self) -> 'Self'
     |      Symbolically simplify matrix values (superclass method)
     |
     |      :return: pose with symbolic elements
     |      :rtype: pose instance
     |
     |      Apply symbolic simplification to every element of every value in the
     |      pose instance.
     |
     |      Example::
     |
     |          >>> a = SE3.Rx(sympy.symbols('theta'))
     |          >>> b = a * a
     |          >>> b
     |          SE3(array([[1, 0, 0, 0.0],
     |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
     |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
     |          [0.0, 0, 0, 1.0]], dtype=object)
     |          >>> b.simplify()
     |          SE3(array([[1, 0, 0, 0],
     |          [0, cos(2*theta), -sin(2*theta), 0],
     |          [0, sin(2*theta), cos(2*theta), 0],
     |          [0, 0, 0, 1.00000000000000]], dtype=object))
     |
     |      .. todo:: No need to simplify the constants in bottom row
     |
     |      :SymPy: supported
     |
     |  stack(self) -> 'NDArray'
     |      Convert to 3-dimensional matrix
     |
     |      :return: 3-dimensional NumPy array
     |      :rtype: ndarray(n,n,m)
     |
     |      Converts the value to a 3-dimensional NumPy array where the values are
     |      stacked along the third axis.  The first two dimensions are given by
     |      ``self.shape``.
     |
     |  strline(self, *args, **kwargs) -> 'str'
     |      Convert pose to compact single line string (superclass method)
     |
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: pose in string format
     |      :rtype: str
     |
     |      Convert pose in a compact single line format. If ``X`` has multiple
     |      values, the string has one pose per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.strline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.strline()
     |          >>> x.strline('angvec')
     |          >>> x.strline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.strline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  __new__(cls, *args, **kwargs)
     |      Create the subclass instance (superclass method)
     |
     |      Create a new instance and call the superclass initializer to enable the
     |      ``UserList`` capabilities.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  N
     |      Dimension of the object's group (superclass property)
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
     |      This corresponds to the dimension of the space, 2D or 3D, to which these
     |      rotations or rigid-body motions apply.
     |
     |      Example::
     |
     |          >>> SE3().N
     |          3
     |          >>> SE2().N
     |          2
     |
     |  about
     |      Succinct summary of object type and length (superclass property)
     |
     |      :return: succinct summary
     |      :rtype: str
     |
     |      Displays the type and the number of elements in compact form, for
     |      example::
     |
     |          >>> x = SE3([SE3() for i in range(20)])
     |          >>> len(x)
     |          20
     |          >>> print(x.about)
     |          SE3[20]
     |
     |  isSE
     |      Test if object belongs to SE(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SE2 or SE3
     |      :rtype: bool
     |
     |  isSO
     |      Test if object belongs to SO(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SO2 or SO3
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'_identity', 'isvalid', 'shape'})
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  isvalid(x, check=True)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  shape
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __init__(self, initlist=None)
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __len__(self)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike4 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike6 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLikePure = typing.Union[typing.List[float], typing.Tuple[fl...nda...
    Callable = typing.Callable
        Deprecated alias to collections.abc.Callable.

        Callable[[int], str] signifies a function that takes a single
        parameter of type int and returns a str.

        The subscription syntax must always be used with exactly two
        values: the argument list and the return type.
        The argument list must be a list of types, a ParamSpec,
        Concatenate or ellipsis. The return type must be a single type.

        There is no syntax to indicate optional or keyword arguments;
        such function types are rarely used as callback types.

    Color = typing.Union[str, typing.List[float], typing.Tup...typing.Lite...
    DTypeLike = typing.Union[numpy.dtype[typing.Any], NoneType, ...e_like....
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    L = typing.Literal
        Special typing form to define literal types (a.k.a. value types).

        This form can be used to indicate to type checkers that the corresponding
        variable or function parameter has a value equivalent to the provided
        literal (or one of several literals)::

            def validate_simple(data: Any) -> Literal[True]:  # always returns True
                ...

            MODE = Literal['r', 'rb', 'w', 'wb']
            def open_helper(file: str, mode: MODE) -> str:
                ...

            open_helper('/some/path', 'r')  # Passes type check
            open_helper('/other/path', 'typo')  # Error in type checker

        Literal[...] cannot be subclassed. At runtime, an arbitrary value
        is allowed as type argument to Literal[...], but type checkers may
        impose restrictions.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Points3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    QuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy...
    R1 = numpy.ndarray[typing.Tuple[typing.Literal[1]], numpy.dtype[numpy....
    R1x1 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[1]...
    R1x2 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[2]...
    R1x3 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[3]...
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R2x1 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[1]...
    R2x2 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]...
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R3x1 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[1]...
    R3x3 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]...
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    R4x4 = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]...
    R6 = numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy....
    R6x6 = numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]...
    R8 = numpy.ndarray[typing.Tuple[typing.Literal[8]], numpy.dtype[numpy....
    R8x8 = numpy.ndarray[typing.Tuple[typing.Literal[8], typing.Literal[8]...
    RNx3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Rn = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.Literal...
    SE2Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SE3Array = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Litera...
    SEnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    SO2Array = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Litera...
    SO3Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SOnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Type = typing.Type
        Deprecated alias to builtins.type.

        builtins.type or typing.Type can be used to annotate class objects.
        For example, suppose we have the following classes::

            class User: ...  # Abstract base for User classes
            class BasicUser(User): ...
            class ProUser(User): ...
            class TeamUser(User): ...

        And a function that takes a class argument that's a subclass of
        User and returns an instance of the corresponding class::

            def new_user[U](user_class: Type[U]) -> U:
                user = user_class()
                # (Here we could write the user object to a database)
                return user

            joe = new_user(BasicUser)

        At this point the type checker knows that joe has type BasicUser.

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

    UnitQuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], n...
    se2Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    se3Array = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[...
    senArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    so2Array = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[...
    so3Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    sonArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\baseposematrix.py

spatialmath-python.geom2d
Python Library Documentation: module spatialmath.geom2d in spatialmath

NAME
    spatialmath.geom2d - Created on Sun Jul  5 09:42:30 2020

DESCRIPTION
    @author: corkep

CLASSES
    builtins.object
        Ellipse
        Line2
            LineSegment2
        Polygon2

    class Ellipse(builtins.object)
     |  Ellipse(radii: 'Optional[ArrayLike2]' = None, E: 'Optional[NDArray]' = None, centre: 'ArrayLike2' = (0, 0), theta: 'Optional[float]' = None)
     |
     |  Methods defined here:
     |
     |  __init__(self, radii: 'Optional[ArrayLike2]' = None, E: 'Optional[NDArray]' = None, centre: 'ArrayLike2' = (0, 0), theta: 'Optional[float]' = None)
     |      Create an ellipse
     |
     |      :param radii: radii of ellipse, defaults to None
     |      :type radii: arraylike(2), optional
     |      :param E: 2x2 matrix describing ellipse, defaults to None
     |      :type E: ndarray(2,2), optional
     |      :param centre: centre of ellipse, defaults to (0, 0)
     |      :type centre: arraylike(2), optional
     |      :param theta: orientation of ellipse, defaults to None
     |      :type theta: float, optional
     |      :raises ValueError: bad parameters
     |
     |      The ellipse shape can be specified by ``radii`` and ``theta`` or by a
     |      symmetric 2x2 matrix ``E``.
     |
     |      Internally the ellipse is represented by a symmetric matrix :math:`\mat{E} \in \mathbb{R}^{2\times 2}`
     |      and its centre coordinate :math:`\vec{x}_0 \in \mathbb{R}^2` such that
     |
     |      .. math::
     |
     |          (\vec{x} - \vec{x}_0)^{\top} \mat{E} \, (\vec{x} - \vec{x}_0) = 1
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> import numpy as np
     |          >>> Ellipse(radii=(1,2), theta=0)
     |          >>> Ellipse(E=np.array([[1, 1], [1, 2]]))
     |
     |  __repr__(self) -> 'str'
     |      Return repr(self).
     |
     |  __str__(self) -> 'str'
     |      Return str(self).
     |
     |  contains(self, p)
     |      Test if points are contained by ellipse
     |
     |      :param p: point or points to test
     |      :type p: arraylike(2), ndarray(2,N)
     |      :return: true if point is contained within ellipse
     |      :rtype: bool or list(bool)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.contains((3,4))
     |          >>> e.contains((0,0))
     |
     |  plot(self, **kwargs) -> 'None'
     |      Plot ellipse
     |
     |      :param kwargs: arguments passed to :func:`~spatialmath.base.graphics.plot_ellipse`
     |      :return: list of artists
     |      :rtype: _type_
     |
     |      Example::
     |
     |          >>> from spatialmath import Ellipse
     |          >>> from spatialmath.base import plotvol2
     |          >>> plotvol2(5)
     |          >>> e = Ellipse(E=np.array([[1, 1], [1, 2]]))
     |          >>> e.plot()
     |          >>> e.plot(filled=True, color='r')
     |
     |
     |      .. plot::
     |
     |          from spatialmath import Ellipse
     |          from spatialmath.base import plotvol2
     |          ax = plotvol2(5)
     |          e = Ellipse(E=np.array([[1, 1], [1, 2]]))
     |          e.plot()
     |          ax.grid()
     |
     |      .. plot::
     |
     |          from spatialmath import Ellipse
     |          from spatialmath.base import plotvol2
     |          ax = plotvol2(5)
     |          e = Ellipse(E=np.array([[1, 1], [1, 2]]))
     |          e.plot(filled=True, color='r')
     |          ax.grid()
     |
     |      :seealso: :func:`~spatialmath.base.graphics.plot_ellipse`
     |
     |  points(self, resolution=20) -> 'Points2'
     |      Generate perimeter points
     |
     |      :param resolution: number of points on circumferance, defaults to 20
     |      :type resolution: int, optional
     |      :return: set of perimeter points
     |      :rtype: Points2
     |
     |      Return a set of ``resolution`` points on the perimeter of the ellipse.  The perimeter
     |      set is not closed, that is, last point != first point.
     |
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.points()[:,:5]  # first 5 points
     |
     |      :seealso: :meth:`polygon` :func:`~spatialmath.base.graphics.ellipse`
     |
     |  polygon(self, resolution=10) -> 'Polygon2'
     |      Approximate with a polygon
     |
     |      :param resolution: number of polygon vertices, defaults to 20
     |      :type resolution: int, optional
     |      :return: a polygon approximating the ellipse
     |      :rtype: :class:`Polygon2` instance
     |
     |      Return a polygon instance with ``resolution`` vertices.  A :class:`Polygon2`` can be
     |      used for intersection testing with lines or other polygons.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.polygon()
     |
     |      :seealso: :meth:`points`
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  FromPerimeter(p: 'Points2') -> 'Self'
     |      Create an ellipse that fits a set of perimeter points
     |
     |      :param p: a set of 2D perimeter points
     |      :type p: ndarray(2,N)
     |      :return: an ellipse instance
     |      :rtype: Ellipse
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> import numpy as np
     |          >>> eref = Ellipse(radii=(1, 2), theta=np.pi / 4, centre=[3, 4])
     |          >>> perim = eref.points()
     |          >>> print(perim.shape)
     |          >>> Ellipse.FromPerimeter(perim)
     |
     |      :seealso: :meth:`points`
     |
     |  FromPoints(p) -> 'Self'
     |      Create an equivalent ellipse from a set of interior points
     |
     |      :param p: a set of 2D interior points
     |      :type p: ndarray(2,N)
     |      :return: an ellipse instance
     |      :rtype: Ellipse
     |
     |      Computes the ellipse that has the same inertia as the set of points.
     |
     |      :seealso: :meth:`FromPerimeter`
     |
     |  Polynomial(e: 'ArrayLike', p: 'Optional[ArrayLike2]' = None) -> 'Self'
     |      Create an ellipse from polynomial
     |
     |      :param e: polynomial coeffients :math:`e` or :math:`\eta`
     |      :type e: arraylike(4) or arraylike(5)
     |      :param p: point to set scale
     |      :type p: array_like(2), optional
     |      :return: an ellipse instance
     |      :rtype: Ellipse
     |
     |      An ellipse can be specified by a polynomial :math:`\vec{e} \in \mathbb{R}^6`
     |
     |      .. math::
     |
     |          e_0 x^2 + e_1 y^2 + e_2 xy + e_3 x + e_4 y + e_5 = 0
     |
     |      or :math:`\vec{\epsilon} \in \mathbb{R}^5` where the leading coefficient is
     |      implicitly one
     |
     |      .. math::
     |
     |          x^2 + \epsilon_1 y^2 + \epsilon_2 xy + \epsilon_3 x + \epsilon_4 y + \epsilon_5 = 0
     |
     |      In this latter case, position, orientation and aspect ratio of the
     |      ellipse will be correct, but the overall scale of the ellipse is not
     |      determined.  To correct this, we can pass in a single point ``p`` that
     |      we know lies on the perimeter of the ellipse.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> Ellipse.Polynomial([0.625, 0.625, 0.75, -6.75, -7.25, 24.625])
     |
     |      :seealso: :meth:`polynomial`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  E
     |      Return ellipse matrix
     |
     |      :return: ellipse matrix
     |      :rtype: ndarray(2,2)
     |
     |      The symmetric matrix :math:`\mat{E} \in \mathbb{R}^{2\times 2}` determines the radii and
     |      the orientation of the ellipse
     |
     |      .. math::
     |
     |          (\vec{x} - \vec{x}_0)^{\top} \mat{E} \, (\vec{x} - \vec{x}_0) = 1
     |
     |      :seealso: :meth:`centre` :meth:`theta` :meth:`radii`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.E
     |
     |  area
     |      Area of ellipse
     |
     |      :return: area
     |      :rtype: float
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.area
     |
     |  centre
     |      Return ellipse centre
     |
     |      :return: centre of the ellipse
     |      :rtype: ndarray(2)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.centre
     |
     |      :seealso: :meth:`radii` :meth:`theta` :meth:`E`
     |
     |  polynomial
     |      Return ellipse as a polynomial
     |
     |      :return: polynomial
     |      :rtype: ndarray(6)
     |
     |      An ellipse can be described by :math:`\vec{e} \in \mathbb{R}^6` which are the
     |      coefficents of a quadratic in :math:`x` and :math:`y`
     |
     |      .. math::
     |
     |          e_0 x^2 + e_1 y^2 + e_2 xy + e_3 x + e_4 y + e_5 = 0
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.polynomial
     |
     |      :seealso: :meth:`Polynomial`
     |
     |  radii
     |      Return radii of the ellipse
     |
     |      :return: radii of the ellipse
     |      :rtype: ndarray(2)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.radii
     |
     |      :seealso: :meth:`centre` :meth:`theta` :meth:`E`
     |
     |  theta
     |      Return orientation of ellipse
     |
     |      :return: orientation in radians, in the interval [-pi, pi)
     |      :rtype: float
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Ellipse
     |          >>> e = Ellipse(radii=(1,2), centre=(3,4), theta=0.5)
     |          >>> e.theta
     |
     |      :seealso: :meth:`centre` :meth:`radii` :meth:`E`
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class Line2(builtins.object)
     |  Line2(line: 'ArrayLike3')
     |
     |  Class to represent 2D lines
     |
     |  The internal representation is in homogeneous format
     |
     |  .. math::
     |
     |          ax + by + c = 0
     |
     |  Methods defined here:
     |
     |  __init__(self, line: 'ArrayLike3')
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __str__(self) -> 'str'
     |      Return str(self).
     |
     |  contains(self, p: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
     |      Test if point is in line
     |
     |      :param p1: point to test
     |      :type p1: array_like(2) or array_like(3)
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: True if point lies in the line
     |      :rtype: bool
     |
     |  contains_polygon_point(self)
     |
     |  distance_line_line(self)
     |      # these should have same names as for 3d case
     |
     |  distance_line_point(self)
     |
     |  general(self) -> 'Tuple[float, float]'
     |      Parameters of general line
     |
     |      :return: parameters of general line (m, c)
     |      :rtype: ndarray(2)
     |
     |      Return the parameters of a general line :math:`y = mx + c`.
     |
     |  intersect(self, other: 'Line2', tol: 'float' = 20) -> 'R3'
     |      Intersection with line
     |
     |      :param other: another 2D line
     |      :type other: Line2
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: intersection point in homogeneous form
     |      :rtype: ndarray(3)
     |
     |      If the lines are parallel then the third element of the returned
     |      homogeneous point will be zero (an ideal point).
     |
     |  intersect_polygon___line(self)
     |
     |  intersect_segment(self, p1: 'ArrayLike2', p2: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
     |      Test for line intersecting line segment
     |
     |      :param p1: start of line segment
     |      :type p1: array_like(2) or array_like(3)
     |      :param p2: end of line segment
     |      :type p2: array_like(2) or array_like(3)
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: True if they intersect
     |      :rtype: bool
     |
     |      Tests whether the line intersects the line segment defined by endpoints
     |      ``p1`` and ``p2`` which are given in Euclidean or homogeneous form.
     |
     |  plot(self, **kwargs) -> 'None'
     |      Plot the line using matplotlib
     |
     |      :param kwargs: arguments passed to Matplotlib ``pyplot.plot``
     |
     |  points_join(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  General(m, c) -> 'Self'
     |      Create line from general line
     |
     |      :param m: line gradient
     |      :type m: float
     |      :param c: line intercept
     |      :type c: float
     |      :return: a 2D line
     |      :rtype: a Line2 instance
     |
     |      Creates a line from the parameters of the general line :math:`y = mx + c`.
     |
     |      .. note:: A vertical line cannot be represented.
     |
     |  Join(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
     |      Create 2D line from two points
     |
     |      :param p1: point on the line
     |      :type p1: array_like(2) or array_like(3)
     |      :param p2: another point on the line
     |      :type p2: array_like(2) or array_like(3)
     |
     |      The points can be given in Euclidean or homogeneous form.
     |
     |  TwoPoints(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class LineSegment2(Line2)
     |  LineSegment2(line: 'ArrayLike3')
     |
     |  Method resolution order:
     |      LineSegment2
     |      Line2
     |      builtins.object
     |
     |  Methods inherited from Line2:
     |
     |  __init__(self, line: 'ArrayLike3')
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __str__(self) -> 'str'
     |      Return str(self).
     |
     |  contains(self, p: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
     |      Test if point is in line
     |
     |      :param p1: point to test
     |      :type p1: array_like(2) or array_like(3)
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: True if point lies in the line
     |      :rtype: bool
     |
     |  contains_polygon_point(self)
     |
     |  distance_line_line(self)
     |      # these should have same names as for 3d case
     |
     |  distance_line_point(self)
     |
     |  general(self) -> 'Tuple[float, float]'
     |      Parameters of general line
     |
     |      :return: parameters of general line (m, c)
     |      :rtype: ndarray(2)
     |
     |      Return the parameters of a general line :math:`y = mx + c`.
     |
     |  intersect(self, other: 'Line2', tol: 'float' = 20) -> 'R3'
     |      Intersection with line
     |
     |      :param other: another 2D line
     |      :type other: Line2
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: intersection point in homogeneous form
     |      :rtype: ndarray(3)
     |
     |      If the lines are parallel then the third element of the returned
     |      homogeneous point will be zero (an ideal point).
     |
     |  intersect_polygon___line(self)
     |
     |  intersect_segment(self, p1: 'ArrayLike2', p2: 'ArrayLike2', tol: 'float' = 20) -> 'bool'
     |      Test for line intersecting line segment
     |
     |      :param p1: start of line segment
     |      :type p1: array_like(2) or array_like(3)
     |      :param p2: end of line segment
     |      :type p2: array_like(2) or array_like(3)
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: True if they intersect
     |      :rtype: bool
     |
     |      Tests whether the line intersects the line segment defined by endpoints
     |      ``p1`` and ``p2`` which are given in Euclidean or homogeneous form.
     |
     |  plot(self, **kwargs) -> 'None'
     |      Plot the line using matplotlib
     |
     |      :param kwargs: arguments passed to Matplotlib ``pyplot.plot``
     |
     |  points_join(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from Line2:
     |
     |  General(m, c) -> 'Self'
     |      Create line from general line
     |
     |      :param m: line gradient
     |      :type m: float
     |      :param c: line intercept
     |      :type c: float
     |      :return: a 2D line
     |      :rtype: a Line2 instance
     |
     |      Creates a line from the parameters of the general line :math:`y = mx + c`.
     |
     |      .. note:: A vertical line cannot be represented.
     |
     |  Join(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
     |      Create 2D line from two points
     |
     |      :param p1: point on the line
     |      :type p1: array_like(2) or array_like(3)
     |      :param p2: another point on the line
     |      :type p2: array_like(2) or array_like(3)
     |
     |      The points can be given in Euclidean or homogeneous form.
     |
     |  TwoPoints(p1: 'ArrayLike2', p2: 'ArrayLike2') -> 'Self'
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from Line2:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class Polygon2(builtins.object)
     |  Polygon2(vertices: 'Optional[Points2]' = None, close: 'bool' = True)
     |
     |  Class to represent 2D (planar) polygons
     |
     |  .. note:: Uses Matplotlib primitives to perform transformations and
     |      intersections.
     |
     |  Methods defined here:
     |
     |  __init__(self, vertices: 'Optional[Points2]' = None, close: 'bool' = True)
     |      Create planar polygon from vertices
     |
     |      :param vertices: vertices of polygon, defaults to None
     |      :type vertices: ndarray(2, N), optional
     |      :param close: closes the polygon, replicates the first vertex, defaults to True
     |      :type closed: bool, optional
     |
     |      Create a polygon from a set of points provided as columns of the 2D
     |      array ``vertices``.
     |      A closed polygon is created so the last vertex should not equal the
     |      first.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |
     |      .. warning:: The points must be sequential around the perimeter and
     |          counter clockwise, otherwise moments will be negative.
     |
     |      .. note:: The polygon is represented by a Matplotlib ``Path``
     |
     |  __len__(self) -> 'int'
     |      Number of vertices in polygon
     |
     |      :return: number of vertices
     |      :rtype: int
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> len(p)
     |
     |  __repr__(self) -> 'str'
     |      Return repr(self).
     |
     |  __str__(self) -> 'str'
     |      Polygon to string
     |
     |      :return: brief summary of polygon
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> import numpy as np
     |          >>> p = Polygon2(np.array([[1, 3, 2], [2, 2, 4]]))
     |          >>> print(p)
     |
     |  animate(self, T, **kwargs) -> 'None'
     |      Animate a polygon
     |
     |      :param T: new pose of Polygon
     |      :type T: SE2
     |      :param kwargs: options passed to Matplotlib ``Patch``
     |
     |      The plotted polygon is moved to the pose given by ``T``. The pose is
     |      always with respect to the initial vertices when the polygon was
     |      constructed.  The vertices of the polygon will be updated to reflect
     |      what is plotted.
     |
     |      If the polygon has already plotted, it will keep the same graphical
     |      attributes.  If new attributes are given they will replace those
     |      given at construction time.
     |
     |      :seealso: :meth:`plot`
     |
     |  area(self) -> 'float'
     |      Area of polygon
     |
     |      :return: area
     |      :rtype: float
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.area()
     |
     |      :seealso: :meth:`moment`
     |
     |  bbox(self) -> 'R4'
     |      Bounding box of polygon
     |
     |      :return: bounding box as [xmin, xmax, ymin, ymax]
     |      :rtype: ndarray(4)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.bbox()
     |
     |  centroid(self) -> 'R2'
     |      Centroid of polygon
     |
     |      :return: centroid
     |      :rtype: ndarray(2)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.centroid()
     |
     |      :seealso: :meth:`moment`
     |
     |  contains(self, p: 'ArrayLike2', radius: 'float' = 0.0) -> 'Union[bool, List[bool]]'
     |      Test if point is inside polygon
     |
     |      :param p: point
     |      :type p: array_like(2)
     |      :param radius: Add an additional margin to the polygon boundary, defaults to 0.0
     |      :type radius: float, optional
     |      :return: True if point is contained by polygon
     |      :rtype: bool
     |
     |      ``radius`` can be used to inflate the polygon, or if negative, to
     |      deflated it.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.contains([0, 0])
     |          >>> p.contains([2, 3])
     |
     |      .. warning:: Returns True if the point is on the edge of the polygon
     |          but False if the point is one of the vertices.
     |
     |      .. warning:: For a polygon with clockwise ordering of vertices the
     |          sign of ``radius`` is flipped.
     |
     |      :seealso: :func:`matplotlib.contains_point`
     |
     |  edges(self) -> 'Iterator'
     |      Iterate over polygon edge segments
     |
     |      Creates an iterator that returns pairs of points representing the
     |      end points of each segment.
     |
     |  intersects(self, other: 'Union[Polygon2, Line2, List[Polygon2], List[Line2]]') -> 'bool'
     |      Test for intersection
     |
     |      :param other: object to test for intersection
     |      :type other: Polygon2 or Line2 or list(Polygon2) or list(Line2)
     |      :return: True if the polygon intersects ``other``
     |      :rtype: bool
     |      :raises ValueError:
     |
     |      Returns true if the polygon intersects the the given polygon or 2D
     |      line. If ``other`` is a list, test against all in the list and return on the
     |      first intersection.
     |
     |  moment(self, p: 'int', q: 'int') -> 'float'
     |      Moments of polygon
     |
     |      :param p: moment order x
     |      :type p: int
     |      :param q: moment order y
     |      :type q: int
     |
     |      Returns the pq'th moment of the polygon
     |
     |      .. math::
     |
     |          M(p, q) = \sum_{i=0}^{n-1} x_i^p y_i^q
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.moment(0, 0)  # area
     |          >>> p.moment(3, 0)
     |
     |      Note is negative for clockwise perimeter.
     |
     |  plot(self, ax: 'Optional[plt.Axes]' = None, **kwargs) -> 'None'
     |      Plot polygon
     |
     |      :param ax: axes in which to draw the polygon, defaults to None
     |      :type ax: Axes, optional
     |      :param kwargs: options passed to Matplotlib ``Patch``
     |
     |      A Matplotlib Patch is created with the passed options ``**kwargs`` and
     |      added to the axes.
     |
     |      Examples::
     |
     |          >>> from spatialmath.base import plotvol2, plot_polygon
     |          >>> plotvol2(5)
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.plot(fill=False)
     |          >>> p.plot(facecolor="g", edgecolor="none")  # green filled triangle
     |
     |      .. plot::
     |
     |          from spatialmath import Polygon2
     |          from spatialmath.base import plotvol2
     |          p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          plotvol2(5)
     |          p.plot(fill=False)
     |
     |      .. plot::
     |
     |          from spatialmath import Polygon2
     |          from spatialmath.base import plotvol2
     |          p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          plotvol2(5)
     |          p.plot(facecolor="g", edgecolor="none")  # green filled triangle
     |
     |
     |      :seealso: :meth:`animate` :func:`matplotlib.PathPatch`
     |
     |  radius(self) -> 'float'
     |      Radius of smallest enclosing circle
     |
     |      :return: radius
     |      :rtype: float
     |
     |      This is the radius of the smalleset circle, centred at the centroid,
     |      that encloses all vertices.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.radius()
     |
     |  transformed(self, T: 'SE2') -> 'Self'
     |      A transformed copy of polygon
     |
     |      :param T: planar transformation
     |      :type T: SE2
     |      :return: transformed polygon
     |      :rtype: Polygon2
     |
     |      Returns a new polgyon whose vertices have been transformed by ``T``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2, SE2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.vertices()
     |          >>> p.transformed(SE2(10, 0, 0)).vertices() # shift by x+10
     |
     |  vertices(self, unique: 'bool' = True) -> 'Points2'
     |      Vertices of polygon
     |
     |      :param unique: return only the unique vertices , defaults to True
     |      :type unique: bool, optional
     |      :return: vertices
     |      :rtype: ndarray(2,n)
     |
     |      Returns the set of vertices.  The polygon is always closed, that is, the first
     |      and last vertices are the same.  The ``unique`` option does not include the last
     |      vertex.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Polygon2
     |          >>> p = Polygon2([(1, 2), (3, 2), (2, 4)])
     |          >>> p.vertices()
     |          >>> p.vertices(closed=True)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

FUNCTIONS
    reduce(...)
        reduce(function, iterable[, initial]) -> value

        Apply a function of two arguments cumulatively to the items of a sequence
        or iterable, from left to right, so as to reduce the iterable to a single
        value.  For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
        ((((1+2)+3)+4)+5).  If initial is present, it is placed before the items
        of the iterable in the calculation, and serves as a default when the
        iterable is empty.

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\geom2d.py

spatialmath-python.geom3d
Python Library Documentation: module spatialmath.geom3d in spatialmath

NAME
    spatialmath.geom3d

DESCRIPTION
    # Part of Spatial Math Toolbox for Python
    # Copyright (c) 2000 Peter Corke
    # MIT Licence, see details in top-level file: LICENCE

CLASSES
    builtins.object
        Plane3
    spatialmath.baseposelist.BasePoseList(collections.UserList, abc.ABC)
        Line3
            Plucker

    class Line3(spatialmath.baseposelist.BasePoseList)
     |  Line3(v=None, w=None, check=True)
     |
     |  Method resolution order:
     |      Line3
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __eq__(l1, l2: 'Line3') -> 'bool'
     |      Test if two lines are equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are equivalent
     |      :rtype: bool
     |
     |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`isequal` :meth:`__ne__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __init__(self, v=None, w=None, check=True)
     |      Create a Line3 object
     |
     |      :param v: Plucker coordinate vector, or Plucker moment vector
     |      :type v: array_like(6) or array_like(3)
     |      :param w: Plucker direction vector, optional
     |      :type w: array_like(3), optional
     |      :param check: check that the parameters are valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad arguments
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      A representation of a 3D line using Plucker coordinates.
     |
     |      - ``Line3(p)`` creates a 3D line from a Plucker coordinate vector ``p=[v, w]``
     |         where ``v`` (3,) is the moment and ``w`` (3,) is the line direction.
     |
     |      - ``Line3(v, w)`` as above but the components ``v`` and ``w`` are
     |        provided separately.
     |
     |      - ``Line3(L)`` creates a copy of the ``Line3`` object ``L``.
     |
     |      :notes:
     |
     |          - The ``Line3`` object inherits from ``collections.UserList`` and has list-like
     |            behaviours.
     |          - A single ``Line3`` object contains a 1D-array of Plucker coordinates.
     |          - The elements of the array are guaranteed to be Plucker coordinates.
     |          - The number of elements is given by ``len(L)``
     |          - The elements can be accessed using index and slice notation, eg. ``L[1]`` or
     |            ``L[2:3]``
     |          - The ``Line3`` instance can be used as an iterator in a for loop or list comprehension.
     |          - Some methods support operations on the internal list.
     |
     |      :seealso: :meth:`Join` :meth:`TwoPlanes` :meth:`PointDir`
     |
     |  __mul__(left, right: 'Line3') -> 'float'
     |      Reciprocal product
     |
     |      :param left: Left operand
     |      :type left: Line3
     |      :param right: Right operand
     |      :type right: Line3
     |      :return: reciprocal product
     |      :rtype: float
     |
     |      ``left * right`` is the scalar reciprocal product :math:`\hat{w}_L \dot m_R + \hat{w}_R \dot m_R`.
     |
     |      .. note::
     |
     |          - Multiplication or composition of lines is not defined.
     |          - Pre-multiplication by an SE3 object is supported, see ``__rmul__``.
     |
     |      :seealso: :meth:`__rmul__`
     |
     |  __ne__(l1, l2: 'Line3') -> 'bool'
     |      Test if two lines are not equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are not equivalent
     |      :rtype: bool
     |
     |      ``L1 != L2`` is True if the Line3 objects describe different lines in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`__ne__`
     |
     |  __or__(l1, l2: 'Line3') -> 'bool'
     |      Overloaded ``|`` operator tests for parallelism
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are parallel
     |      :rtype: bool
     |
     |      ``l1 | l2`` is an operator which is true if the two lines are parallel.
     |
     |      .. note:: The ``|`` operator has low precendence.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`isparallel` :meth:`__xor__`
     |
     |  __repr__(self) -> 'str'
     |      Display Line3
     |
     |      :return: String representation of line parameters
     |      :rtype: str
     |
     |      Displays the line parameters in compact single line format.
     |
     |      For a multi-valued ``Line3``, one line per value in ``Line3``.
     |
     |  __rmul__(right, left: 'SE3') -> 'Line3'
     |      Rigid-body transformation of 3D line
     |
     |      :param left: Rigid-body transform
     |      :type left: SE3
     |      :param right: 3D line
     |      :type right: Line
     |      :return: transformed 3D line
     |      :rtype: Line3 instance
     |
     |      ``T * line`` is the line transformed by the rigid body transformation ``T``.
     |
     |      :seealso: :meth:`__mul__`
     |
     |  __str__(self) -> 'str'
     |      Convert Line3 to a string
     |
     |      :return: String representation of line parameters
     |      :rtype: str
     |
     |      ``str(line)`` is a string showing Plucker parameters in a compact single
     |      line format like::
     |
     |          { 0 0 0; -1 -2 -3}
     |
     |      where the first three numbers are the moment, and the last three are the
     |      direction vector.
     |
     |      For a multi-valued ``Line3``, one line per value in ``Line3``.
     |
     |  __xor__(l1, l2: 'Line3') -> 'bool'
     |      Overloaded ``^`` operator tests for intersection
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :return: lines intersect
     |      :rtype: bool
     |
     |      ``l1 ^ l2`` is an operator which is true if the two lines intersect.
     |
     |      .. note::
     |
     |          - The ``^`` operator has low precendence.
     |          - Is ``False`` if the lines are equivalent since they would intersect at
     |            an infinite number of points.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`intersects` :meth:`isparallel` :meth:`isintersecting`
     |
     |  append(self, x: 'Line3')
     |      Append a line
     |
     |      :param x: line object
     |      :type x: Line3
     |      :raises ValueError: Attempt to append a non Plucker object
     |      :return: Line3 object with new line appended
     |      :rtype: Line3 instance
     |
     |  closest_to_line(l1, l2: 'Line3') -> 'Tuple[Points3, Rn]'
     |      Closest point between lines
     |
     |      :param l2: second line
     |      :type l2: Line3
     |      :return: nearest points and distance between lines at those points
     |      :rtype: ndarray(3,N), ndarray(N)
     |
     |      There are four cases:
     |
     |      * ``len(self) == len(other) == 1`` find the point on the first line closest to the second line, as well
     |        as the minimum distance between the lines.
     |      * ``len(self) == 1, len(other) == N`` find the point of intersection between the first
     |        line and the ``N`` other lines, returning ``N`` intersection points and distances.
     |      * ``len(self) == N, len(other) == 1`` find the point of intersection between the ``N`` first
     |        lines and the other line, returning ``N`` intersection points and distances.
     |      * ``len(self) == N, len(other) == M`` for each  of the ``N`` first
     |        lines find the closest intersection with each of the ``M`` other lines, returning ``N``
     |        intersection points and distances.
     |
     |      ** this last one should be an option, default behavior would be to
     |      test self[i] against line[i]
     |      ** maybe different function
     |
     |      For two sets of lines, of equal size, return an array of closest points
     |      and distances.
     |
     |      Example::
     |
     |          .. runblock:: pycon
     |
     |              >>> from spatialmath import Line3
     |              >>> line1 = Line3.Join([1, 1, 0], [1, 1, 1])
     |              >>> line2 = Line3.Join([0, 0, 0], [2, 3, 5])
     |              >>> line1.closest_to_line(line2)
     |
     |      :reference: `Plucker coordinates <https://web.cs.iastate.edu/~cs577/handouts/plucker-coordinates.pdf>`_
     |
     |
     |      :seealso: :meth:`distance`
     |
     |  closest_to_point(self, x: 'ArrayLike3') -> 'Tuple[R3, float]'
     |      Point on line closest to given point
     |
     |      :param x: An arbitrary 3D point
     |      :type x: array_like(3)
     |      :return: Point on the line and distance to line
     |      :rtype: ndarray(3), float
     |
     |      Find the point on the line closest to ``x`` as well as the distance
     |      at that closest point.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Line3
     |          >>> line1 = Line3.Join([0, 0, 0], [2, 2, 3])
     |          >>> line1.closest_to_point([1, 1, 1])
     |
     |      :seealso: meth:`point`
     |
     |  commonperp(l1, l2: 'Line3') -> 'Line3'
     |      Common perpendicular to two lines
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :return: Perpendicular line
     |      :rtype: Line3 instance or None
     |
     |      ``l1.commonperp(l2)`` is the common perpendicular line between the two lines.
     |      Returns ``None`` if the lines are parallel.
     |
     |      :seealso: :meth:`intersect`
     |
     |  contains(self, x: 'Union[R3, Points3]', tol: 'float' = 20) -> 'Union[bool, List[bool]]'
     |      Test if points are on the line
     |
     |      :param x: 3D point
     |      :type x: 3-element array_like, or ndarray(3,N)
     |      :param tol: Tolerance in units of eps, defaults to 20
     |      :type tol: float, optional
     |      :raises ValueError: Bad argument
     |      :return: Whether point is on the line
     |      :rtype: bool or numpy.ndarray(N) of bool
     |
     |      ``line.contains(X)`` is true if the point ``X`` lies on the line defined by
     |      the Line3 object self.
     |
     |      If ``X`` is an array with 3 rows, the test is performed on every column and
     |      an array of booleans is returned.
     |
     |  distance(l1, l2: 'Line3', tol: 'float' = 20) -> 'float'
     |      Minimum distance between lines
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: Closest distance between lines
     |      :rtype: float
     |
     |      ``l1.distance(l2) is the minimum distance between two lines.
     |
     |      .. note:: Works for parallel, skew and intersecting lines.
     |
     |      :seealso: :meth:`closest_to_line`
     |
     |  intersect_plane(self, plane: 'Union[ArrayLike4, Plane3]', tol: 'float' = 20) -> 'Tuple[R3, float]'
     |      Line intersection with a plane
     |
     |      :param plane: A plane
     |      :type plane: array_like(4) or Plane3
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: Intersection point, λ
     |      :rtype: ndarray(3), float
     |
     |      - ``P, λ = line.intersect_plane(plane)`` is the point where the line
     |        intersects the plane, and the corresponding λ value.
     |        Return None, None if no intersection.
     |
     |      The plane can be specified as:
     |
     |       - a 4-vector :math:`[a, b, c, d]` which describes the plane :math:`\pi: ax + by + cz + d=0`.
     |       - a ``Plane`` object
     |
     |       The return value is a named tuple with elements:
     |
     |          - ``.p`` for the point on the line as a numpy.ndarray, shape=(3,)
     |          - ``.lam`` the `lambda` value for the point on the line.
     |
     |      :sealso: :meth:`point` :class:`Plane`
     |
     |  intersect_volume(self, bounds: 'ArrayLike6') -> 'Tuple[Points3, Rn]'
     |      Line intersection with a volume
     |
     |      :param bounds: Bounds of an axis-aligned rectangular cuboid
     |      :type plane: array_like(6)
     |      :return: Intersection point, λ value
     |      :rtype: ndarray(3,N), ndarray(N)
     |
     |      ``P, λ = line.intersect_volume(bounds)`` is a matrix (3xN) with columns
     |      that indicate where the line intersects the faces of the volume and
     |      the corresponding λ values.
     |
     |      The volume is specified by ``bounds`` = [xmin xmax ymin ymax zmin zmax].
     |
     |      The number of
     |      columns N is either:
     |
     |      - 0, when the line is outside the plot volume or,
     |      - 2 when the line pierces the bounding volume.
     |
     |
     |      See also :meth:`plot` :meth:`point`
     |
     |  intersects(l1, l2: 'Line3') -> 'Union[R3, None]'
     |      Intersection point of two lines
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: 3D intersection point
     |      :rtype: ndarray(3) or None
     |
     |      ``l1.intersects(l2)`` is the point of intersection of the two lines, or
     |      ``None`` if the lines do not intersect or are equivalent.
     |
     |      :seealso: :meth:`commonperp :meth:`eq` :meth:`__xor__`
     |
     |  isequal(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if two lines are equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines are equivalent
     |      :rtype: bool
     |
     |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      :seealso: :meth:`__eq__`
     |
     |  isintersecting(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if lines are intersecting
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines intersect
     |      :rtype: bool
     |
     |      ``l1.isintersecting(l2)`` is true if the two lines intersect.
     |
     |      .. note:: Is ``False`` if the lines are equivalent since they would intersect at
     |            an infinite number of points.
     |
     |      :seealso: :meth:`__xor__` :meth:`intersects` :meth:`isparallel`
     |
     |  isparallel(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if lines are parallel
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines are parallel
     |      :rtype: bool
     |
     |      ``l1.isparallel(l2)`` is true if the two lines are parallel.
     |
     |      ``l1 | l2`` as above but in binary operator form
     |
     |      :seealso: :meth:`__or__` :meth:`intersects`
     |
     |  lam(self, point: 'ArrayLike3') -> 'float'
     |      Parametric distance from principal point
     |
     |      :param point: 3D point
     |      :type point: array_like(3)
     |      :return: parametric distance λ
     |      :rtype: float
     |
     |      ``line.lam(P)`` is the value of :math:`\lambda` such that
     |      :math:`Q = P_p + \lambda \hat{d}` is closest to ``P``.
     |
     |      :seealso: :meth:`point`
     |
     |  plot(self, *pos, bounds: 'Optional[ArrayLike]' = None, ax: 'Optional[plt.Axes]' = None, **kwargs) -> 'List[plt.Artist]'
     |       Plot a line
     |
     |      :param bounds: Bounds of an axis-aligned rectangular cuboid as [xmin xmax ymin ymax zmin zmax], optional
     |      :type plane: 6-element array_like
     |      :param **kwargs: Extra arguents passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
     |      :return: Plotted line
     |      :rtype: Matplotlib artists
     |
     |      - ``line.plot(bounds)`` adds a line segment to the current axes, and the handle of the line is returned.
     |        The line segment is defined by the intersection of the line and the given rectangular cuboid.
     |        If the line does not intersect the plotting volume None is returned.
     |
     |      - ``line.plot()`` as above but the bounds are taken from the axis limits of the current axes.
     |
     |      The line color or style is specified by:
     |
     |          - a  MATLAB-style linestyle like 'k--'
     |          - additional arguments passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
     |
     |      :seealso: :meth:`intersect_volume`
     |
     |  point(self, lam: 'Union[float, ArrayLike]') -> 'Points3'
     |      Generate point on line
     |
     |      :param lam: Scalar distance from principal point
     |      :type lam: float
     |      :return: Distance from principal point to the origin
     |      :rtype: float
     |
     |      ``line.point(λ)`` is a point on the line, where ``λ`` is the parametric
     |      distance along the line from the principal point of the line such
     |      that :math:`P = P_p + \lambda \hat{d}` and :math:`\hat{d}` is the line
     |      direction given by ``line.uw``.
     |
     |      :seealso: :meth:`pp` :meth:`closest` :meth:`uw` :meth:`lam`
     |
     |  side(self, other: 'Line3') -> 'float'
     |      Plucker side operator
     |
     |      :param other: second line
     |      :type other: Line3
     |      :return: permuted dot product
     |      :rtype: float
     |
     |      This permuted dot product operator is zero whenever the lines intersect or are parallel.
     |
     |  skew(self) -> 'R4x4'
     |      Line as a Plucker skew-symmetric matrix
     |
     |      :return: Skew-symmetric matrix form of Plucker coordinates
     |      :rtype: ndarray(4,4)
     |
     |      ``line.skew()`` is the Plucker matrix, a 4x4 skew-symmetric matrix
     |      representation of the line whose six unique elements are the
     |      Plucker coordinates of the line.
     |
     |      .. math::
     |
     |          \sk{L} = \begin{bmatrix} 0 & v_z & -v_y & \omega_x \\
     |              -v_z & 0 & v_x & \omega_y \\
     |              v_y & -v_x & 0 & \omega_z \\
     |              -\omega_x & -\omega_y & -\omega_z & 0 \end{bmatrix}
     |
     |      .. note::
     |
     |          - For two homogeneous points P and Q on the line, :math:`PQ^T-QP^T` is
     |          also skew symmetric.
     |          - The projection of Plucker line by a perspective camera is a
     |          homogeneous line (3x1) given by :math:`\vee C M C^T` where :math:`C
     |          \in \mathbf{R}^{3 \times 4}` is the camera matrix.
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  IntersectingPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
     |
     |  Join(P: 'ArrayLike3', Q: 'ArrayLike3') -> 'Self'
     |      Create 3D line from two 3D points
     |
     |      :param P: First 3D point
     |      :type P: array_like(3)
     |      :param Q: Second 3D point
     |      :type Q: array_like(3)
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``Line3.Join(P, Q)`` create a ``Line3`` object that represents
     |      the line joining the 3D points ``P`` (3,) and ``Q`` (3,). The direction
     |      is from ``Q`` to ``P``.
     |
     |      :seealso: :meth:`IntersectingPlanes` :meth:`PointDir`
     |
     |  PointDir(point: 'ArrayLike3', dir: 'ArrayLike3') -> 'Self'
     |      Create 3D line from a point and direction
     |
     |      :param point: A 3D point
     |      :type point: array_like(3)
     |      :param dir: Direction vector
     |      :type dir: array_like(3)
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``Line3.PointDir(P, W)`` is a `Line3`` object that represents the
     |      line containing the point ``P`` and parallel to the direction vector ``W``.
     |
     |      :seealso: :meth:`Join` :meth:`IntersectingPlanes`
     |
     |  TwoPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
     |      Create 3D line from intersection of two planes
     |
     |      :param pi1: First plane
     |      :type pi1: array_like(4), or ``Plane``
     |      :param pi2: Second plane
     |      :type pi2: array_like(4), or ``Plane``
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``L = Line3.TwoPlanes(π1, π2)`` is a ``Line3`` object that represents
     |      the line formed by the intersection of two planes ``π1`` and ``π3``.
     |
     |      Planes are represented by the 4-vector :math:`[a, b, c, d]` which describes
     |      the plane :math:`\pi: ax + by + cz + d=0`.
     |
     |      :seealso: :meth:`Join` :meth:`PointDir`
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x: 'NDArray', check: 'bool' = False) -> 'bool'
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  pp
     |      Principal point of the 3D line
     |
     |      :return: Principal point of the line
     |      :rtype: ndarray(3)
     |
     |      ``line.pp`` is the point on the line that is closest to the origin.
     |
     |      Notes:
     |
     |       - Same as Plucker.point(0)
     |
     |      :seealso: :meth:`ppd` :meth`point`
     |
     |  ppd
     |      Distance from principal point to the origin
     |
     |      :return: Distance from principal point to the origin
     |      :rtype: float
     |
     |      ``line.ppd`` is the distance from the principal point to the origin.
     |      This is the smallest distance of any point on the line
     |      to the origin.
     |
     |      :seealso: :meth:`pp`
     |
     |  shape
     |
     |  uw
     |      Line direction as a unit vector
     |
     |      :return: Line direction as a unit vector
     |      :rtype: ndarray(3,)
     |
     |      ``line.uw`` is a unit-vector parallel to the line.
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`w`
     |
     |  v
     |      Moment vector
     |
     |      :return: the moment vector
     |      :rtype: ndarray(3)
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`w`
     |
     |  vec
     |      Line as a Plucker coordinate vector
     |
     |      :return: Plucker coordinate vector
     |      :rtype: ndarray(6,)
     |
     |      ``line.vec`` is the  Plucker coordinate vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |  w
     |      Direction vector
     |
     |      :return: the direction vector
     |      :rtype: ndarray(3)
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`v` :meth:`uw`
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class Plane3(builtins.object)
     |  Plane3(c: 'ArrayLike4')
     |
     |  Create a plane object from linear coefficients
     |
     |  :param c: Plane coefficients
     |  :type c: array_like(4)
     |  :return: a Plane object
     |  :rtype: Plane
     |
     |  Planes are represented by the 4-vector :math:`[a, b, c, d]` which describes
     |  the plane :math:`\pi: ax + by + cz + d=0`.
     |
     |  Methods defined here:
     |
     |  __init__(self, c: 'ArrayLike4')
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __repr__(self) -> 'str'
     |      Display parameters of plane
     |
     |      :return: Compact string representation of plane
     |      :rtype: str
     |
     |  __str__(self) -> 'str'
     |      Convert plane to string representation
     |
     |      :return: Compact string representation of plane
     |      :rtype: str
     |
     |  contains(self, p: 'ArrayLike3', tol: 'float' = 20) -> 'bool'
     |      Test if point in plane
     |
     |      :param p: A 3D point
     |      :type p: array_like(3)
     |      :param tol: tolerance in units of eps, defaults to 20
     |      :type tol: float
     |      :return: if the point is in the plane
     |      :rtype: bool
     |
     |  plot(self, bounds: 'Optional[ArrayLike]' = None, ax: 'Optional[plt.Axes]' = None, **kwargs)
     |      Plot plane
     |
     |      :param bounds: bounds of plot volume, defaults to None
     |      :type bounds: array_like(2|4|6), optional
     |      :param ax: 3D axes to plot into, defaults to None
     |      :type ax: Axes, optional
     |      :param kwargs: optional arguments passed to ``plot_surface``
     |
     |      The ``bounds`` of the 3D plot volume is [xmin, xmax, ymin, ymax, zmin, zmax]
     |      and a 3D plot is created if not already existing.  If ``bounds`` is not
     |      provided it is taken from current 3D axes.
     |
     |      The plane is drawn using ``plot_surface``.
     |
     |      :seealso: :func:`axes_logic`
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  LinePoint(l: 'Line3', p: 'ArrayLike3') -> 'Self'
     |      Create a plane object from a line and point
     |
     |      :param l: 3D line
     |      :type l: Line3
     |      :param p: Points in the plane
     |      :type p: ndarray(3)
     |      :return: a Plane object
     |      :rtype: Plane
     |
     |      :seealso: :meth:`PointNormal`  :meth:`ThreePoints`
     |
     |  PointNormal(p: 'ArrayLike3', n: 'ArrayLike3') -> 'Self'
     |      Create a plane object from point and normal
     |
     |      :param p: Point in the plane
     |      :type p: array_like(3)
     |      :param n: Normal vector to the plane
     |      :type n: array_like(3)
     |      :return: a Plane object
     |      :rtype: Plane
     |
     |      :seealso: :meth:`ThreePoints` :meth:`LinePoint`
     |
     |  ThreePoints(p: 'R3x3') -> 'Self'
     |      Create a plane object from three points
     |
     |      :param p: Three points in the plane
     |      :type p: ndarray(3,3)
     |      :return: a Plane object
     |      :rtype: Plane
     |
     |      The points in ``p`` are arranged as columns.
     |
     |      :seealso: :meth:`PointNormal`  :meth:`LinePoint`
     |
     |  TwoLines(l1: 'Line3', l2: 'Line3') -> 'Self'
     |      Create a plane object from two line
     |
     |      :param l1: 3D line
     |      :type l1: Line3
     |      :param l2: 3D line
     |      :type l2: Line3
     |      :return: a Plane object
     |      :rtype: Plane
     |
     |      .. warning:: This algorithm fails if the lines are parallel.
     |
     |      :seealso: :meth:`LinePoint` :meth:`PointNormal`  :meth:`ThreePoints`
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  intersection(pi1: 'Plane3', pi2: 'Plane3', pi3: 'Plane3') -> 'R3'
     |      Intersection point of three planes
     |
     |      :param pi1: plane 1
     |      :type pi1: Plane
     |      :param pi2: plane 2
     |      :type pi2: Plane
     |      :param pi3: plane 3
     |      :type pi3: Plane
     |      :return: coordinates of intersection point
     |      :rtype: ndarray(3)
     |
     |      This static method computes the intersection point of the three planes
     |      given as arguments.
     |
     |      .. warning:: This algorithm fails if the planes do not intersect, or
     |          intersect along a line.
     |
     |      :seealso: :meth:`Plane`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  d
     |      Plane offset
     |
     |      :return: Offset of the plane
     |      :rtype: float
     |
     |      For a plane :math:`\pi: ax + by + cz + d=0` this is the scalar
     |      :math:`d`.
     |
     |
     |      :seealso: :meth:`n`
     |
     |  n
     |      Normal to the plane
     |
     |      :return: Normal to the plane
     |      :rtype: ndarray(3)
     |
     |      For a plane :math:`\pi: ax + by + cz + d=0` this is the vector
     |      :math:`[a,b,c]`.
     |
     |      :seealso: :meth:`d`
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class Plucker(Line3)
     |  Plucker(v=None, w=None)
     |
     |  Method resolution order:
     |      Plucker
     |      Line3
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, v=None, w=None)
     |      Create a Line3 object
     |
     |      :param v: Plucker coordinate vector, or Plucker moment vector
     |      :type v: array_like(6) or array_like(3)
     |      :param w: Plucker direction vector, optional
     |      :type w: array_like(3), optional
     |      :param check: check that the parameters are valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad arguments
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      A representation of a 3D line using Plucker coordinates.
     |
     |      - ``Line3(p)`` creates a 3D line from a Plucker coordinate vector ``p=[v, w]``
     |         where ``v`` (3,) is the moment and ``w`` (3,) is the line direction.
     |
     |      - ``Line3(v, w)`` as above but the components ``v`` and ``w`` are
     |        provided separately.
     |
     |      - ``Line3(L)`` creates a copy of the ``Line3`` object ``L``.
     |
     |      :notes:
     |
     |          - The ``Line3`` object inherits from ``collections.UserList`` and has list-like
     |            behaviours.
     |          - A single ``Line3`` object contains a 1D-array of Plucker coordinates.
     |          - The elements of the array are guaranteed to be Plucker coordinates.
     |          - The number of elements is given by ``len(L)``
     |          - The elements can be accessed using index and slice notation, eg. ``L[1]`` or
     |            ``L[2:3]``
     |          - The ``Line3`` instance can be used as an iterator in a for loop or list comprehension.
     |          - Some methods support operations on the internal list.
     |
     |      :seealso: :meth:`Join` :meth:`TwoPlanes` :meth:`PointDir`
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from Line3:
     |
     |  __eq__(l1, l2: 'Line3') -> 'bool'
     |      Test if two lines are equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are equivalent
     |      :rtype: bool
     |
     |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`isequal` :meth:`__ne__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __mul__(left, right: 'Line3') -> 'float'
     |      Reciprocal product
     |
     |      :param left: Left operand
     |      :type left: Line3
     |      :param right: Right operand
     |      :type right: Line3
     |      :return: reciprocal product
     |      :rtype: float
     |
     |      ``left * right`` is the scalar reciprocal product :math:`\hat{w}_L \dot m_R + \hat{w}_R \dot m_R`.
     |
     |      .. note::
     |
     |          - Multiplication or composition of lines is not defined.
     |          - Pre-multiplication by an SE3 object is supported, see ``__rmul__``.
     |
     |      :seealso: :meth:`__rmul__`
     |
     |  __ne__(l1, l2: 'Line3') -> 'bool'
     |      Test if two lines are not equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are not equivalent
     |      :rtype: bool
     |
     |      ``L1 != L2`` is True if the Line3 objects describe different lines in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`__ne__`
     |
     |  __or__(l1, l2: 'Line3') -> 'bool'
     |      Overloaded ``|`` operator tests for parallelism
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: lines are parallel
     |      :rtype: bool
     |
     |      ``l1 | l2`` is an operator which is true if the two lines are parallel.
     |
     |      .. note:: The ``|`` operator has low precendence.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`isparallel` :meth:`__xor__`
     |
     |  __repr__(self) -> 'str'
     |      Display Line3
     |
     |      :return: String representation of line parameters
     |      :rtype: str
     |
     |      Displays the line parameters in compact single line format.
     |
     |      For a multi-valued ``Line3``, one line per value in ``Line3``.
     |
     |  __rmul__(right, left: 'SE3') -> 'Line3'
     |      Rigid-body transformation of 3D line
     |
     |      :param left: Rigid-body transform
     |      :type left: SE3
     |      :param right: 3D line
     |      :type right: Line
     |      :return: transformed 3D line
     |      :rtype: Line3 instance
     |
     |      ``T * line`` is the line transformed by the rigid body transformation ``T``.
     |
     |      :seealso: :meth:`__mul__`
     |
     |  __str__(self) -> 'str'
     |      Convert Line3 to a string
     |
     |      :return: String representation of line parameters
     |      :rtype: str
     |
     |      ``str(line)`` is a string showing Plucker parameters in a compact single
     |      line format like::
     |
     |          { 0 0 0; -1 -2 -3}
     |
     |      where the first three numbers are the moment, and the last three are the
     |      direction vector.
     |
     |      For a multi-valued ``Line3``, one line per value in ``Line3``.
     |
     |  __xor__(l1, l2: 'Line3') -> 'bool'
     |      Overloaded ``^`` operator tests for intersection
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :return: lines intersect
     |      :rtype: bool
     |
     |      ``l1 ^ l2`` is an operator which is true if the two lines intersect.
     |
     |      .. note::
     |
     |          - The ``^`` operator has low precendence.
     |          - Is ``False`` if the lines are equivalent since they would intersect at
     |            an infinite number of points.
     |
     |      .. note:: There is a hardwired tolerance of 10eps.
     |
     |      :seealso: :meth:`intersects` :meth:`isparallel` :meth:`isintersecting`
     |
     |  append(self, x: 'Line3')
     |      Append a line
     |
     |      :param x: line object
     |      :type x: Line3
     |      :raises ValueError: Attempt to append a non Plucker object
     |      :return: Line3 object with new line appended
     |      :rtype: Line3 instance
     |
     |  closest_to_line(l1, l2: 'Line3') -> 'Tuple[Points3, Rn]'
     |      Closest point between lines
     |
     |      :param l2: second line
     |      :type l2: Line3
     |      :return: nearest points and distance between lines at those points
     |      :rtype: ndarray(3,N), ndarray(N)
     |
     |      There are four cases:
     |
     |      * ``len(self) == len(other) == 1`` find the point on the first line closest to the second line, as well
     |        as the minimum distance between the lines.
     |      * ``len(self) == 1, len(other) == N`` find the point of intersection between the first
     |        line and the ``N`` other lines, returning ``N`` intersection points and distances.
     |      * ``len(self) == N, len(other) == 1`` find the point of intersection between the ``N`` first
     |        lines and the other line, returning ``N`` intersection points and distances.
     |      * ``len(self) == N, len(other) == M`` for each  of the ``N`` first
     |        lines find the closest intersection with each of the ``M`` other lines, returning ``N``
     |        intersection points and distances.
     |
     |      ** this last one should be an option, default behavior would be to
     |      test self[i] against line[i]
     |      ** maybe different function
     |
     |      For two sets of lines, of equal size, return an array of closest points
     |      and distances.
     |
     |      Example::
     |
     |          .. runblock:: pycon
     |
     |              >>> from spatialmath import Line3
     |              >>> line1 = Line3.Join([1, 1, 0], [1, 1, 1])
     |              >>> line2 = Line3.Join([0, 0, 0], [2, 3, 5])
     |              >>> line1.closest_to_line(line2)
     |
     |      :reference: `Plucker coordinates <https://web.cs.iastate.edu/~cs577/handouts/plucker-coordinates.pdf>`_
     |
     |
     |      :seealso: :meth:`distance`
     |
     |  closest_to_point(self, x: 'ArrayLike3') -> 'Tuple[R3, float]'
     |      Point on line closest to given point
     |
     |      :param x: An arbitrary 3D point
     |      :type x: array_like(3)
     |      :return: Point on the line and distance to line
     |      :rtype: ndarray(3), float
     |
     |      Find the point on the line closest to ``x`` as well as the distance
     |      at that closest point.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Line3
     |          >>> line1 = Line3.Join([0, 0, 0], [2, 2, 3])
     |          >>> line1.closest_to_point([1, 1, 1])
     |
     |      :seealso: meth:`point`
     |
     |  commonperp(l1, l2: 'Line3') -> 'Line3'
     |      Common perpendicular to two lines
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :return: Perpendicular line
     |      :rtype: Line3 instance or None
     |
     |      ``l1.commonperp(l2)`` is the common perpendicular line between the two lines.
     |      Returns ``None`` if the lines are parallel.
     |
     |      :seealso: :meth:`intersect`
     |
     |  contains(self, x: 'Union[R3, Points3]', tol: 'float' = 20) -> 'Union[bool, List[bool]]'
     |      Test if points are on the line
     |
     |      :param x: 3D point
     |      :type x: 3-element array_like, or ndarray(3,N)
     |      :param tol: Tolerance in units of eps, defaults to 20
     |      :type tol: float, optional
     |      :raises ValueError: Bad argument
     |      :return: Whether point is on the line
     |      :rtype: bool or numpy.ndarray(N) of bool
     |
     |      ``line.contains(X)`` is true if the point ``X`` lies on the line defined by
     |      the Line3 object self.
     |
     |      If ``X`` is an array with 3 rows, the test is performed on every column and
     |      an array of booleans is returned.
     |
     |  distance(l1, l2: 'Line3', tol: 'float' = 20) -> 'float'
     |      Minimum distance between lines
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: Closest distance between lines
     |      :rtype: float
     |
     |      ``l1.distance(l2) is the minimum distance between two lines.
     |
     |      .. note:: Works for parallel, skew and intersecting lines.
     |
     |      :seealso: :meth:`closest_to_line`
     |
     |  intersect_plane(self, plane: 'Union[ArrayLike4, Plane3]', tol: 'float' = 20) -> 'Tuple[R3, float]'
     |      Line intersection with a plane
     |
     |      :param plane: A plane
     |      :type plane: array_like(4) or Plane3
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: Intersection point, λ
     |      :rtype: ndarray(3), float
     |
     |      - ``P, λ = line.intersect_plane(plane)`` is the point where the line
     |        intersects the plane, and the corresponding λ value.
     |        Return None, None if no intersection.
     |
     |      The plane can be specified as:
     |
     |       - a 4-vector :math:`[a, b, c, d]` which describes the plane :math:`\pi: ax + by + cz + d=0`.
     |       - a ``Plane`` object
     |
     |       The return value is a named tuple with elements:
     |
     |          - ``.p`` for the point on the line as a numpy.ndarray, shape=(3,)
     |          - ``.lam`` the `lambda` value for the point on the line.
     |
     |      :sealso: :meth:`point` :class:`Plane`
     |
     |  intersect_volume(self, bounds: 'ArrayLike6') -> 'Tuple[Points3, Rn]'
     |      Line intersection with a volume
     |
     |      :param bounds: Bounds of an axis-aligned rectangular cuboid
     |      :type plane: array_like(6)
     |      :return: Intersection point, λ value
     |      :rtype: ndarray(3,N), ndarray(N)
     |
     |      ``P, λ = line.intersect_volume(bounds)`` is a matrix (3xN) with columns
     |      that indicate where the line intersects the faces of the volume and
     |      the corresponding λ values.
     |
     |      The volume is specified by ``bounds`` = [xmin xmax ymin ymax zmin zmax].
     |
     |      The number of
     |      columns N is either:
     |
     |      - 0, when the line is outside the plot volume or,
     |      - 2 when the line pierces the bounding volume.
     |
     |
     |      See also :meth:`plot` :meth:`point`
     |
     |  intersects(l1, l2: 'Line3') -> 'Union[R3, None]'
     |      Intersection point of two lines
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :return: 3D intersection point
     |      :rtype: ndarray(3) or None
     |
     |      ``l1.intersects(l2)`` is the point of intersection of the two lines, or
     |      ``None`` if the lines do not intersect or are equivalent.
     |
     |      :seealso: :meth:`commonperp :meth:`eq` :meth:`__xor__`
     |
     |  isequal(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if two lines are equivalent
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines are equivalent
     |      :rtype: bool
     |
     |      ``L1 == L2`` is True if the ``Line3`` objects describe the same line in
     |      space.  Note that because of the over parameterization, lines can be
     |      equivalent even if their coordinate vectors are different.
     |
     |      :seealso: :meth:`__eq__`
     |
     |  isintersecting(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if lines are intersecting
     |
     |      :param l2: Second line
     |      :type l2: Line3
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines intersect
     |      :rtype: bool
     |
     |      ``l1.isintersecting(l2)`` is true if the two lines intersect.
     |
     |      .. note:: Is ``False`` if the lines are equivalent since they would intersect at
     |            an infinite number of points.
     |
     |      :seealso: :meth:`__xor__` :meth:`intersects` :meth:`isparallel`
     |
     |  isparallel(l1, l2: 'Line3', tol: 'float' = 20) -> 'bool'
     |      Test if lines are parallel
     |
     |      :param l2: Second line
     |      :type l2: ``Line3``
     |      :param tol: Tolerance in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: lines are parallel
     |      :rtype: bool
     |
     |      ``l1.isparallel(l2)`` is true if the two lines are parallel.
     |
     |      ``l1 | l2`` as above but in binary operator form
     |
     |      :seealso: :meth:`__or__` :meth:`intersects`
     |
     |  lam(self, point: 'ArrayLike3') -> 'float'
     |      Parametric distance from principal point
     |
     |      :param point: 3D point
     |      :type point: array_like(3)
     |      :return: parametric distance λ
     |      :rtype: float
     |
     |      ``line.lam(P)`` is the value of :math:`\lambda` such that
     |      :math:`Q = P_p + \lambda \hat{d}` is closest to ``P``.
     |
     |      :seealso: :meth:`point`
     |
     |  plot(self, *pos, bounds: 'Optional[ArrayLike]' = None, ax: 'Optional[plt.Axes]' = None, **kwargs) -> 'List[plt.Artist]'
     |       Plot a line
     |
     |      :param bounds: Bounds of an axis-aligned rectangular cuboid as [xmin xmax ymin ymax zmin zmax], optional
     |      :type plane: 6-element array_like
     |      :param **kwargs: Extra arguents passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
     |      :return: Plotted line
     |      :rtype: Matplotlib artists
     |
     |      - ``line.plot(bounds)`` adds a line segment to the current axes, and the handle of the line is returned.
     |        The line segment is defined by the intersection of the line and the given rectangular cuboid.
     |        If the line does not intersect the plotting volume None is returned.
     |
     |      - ``line.plot()`` as above but the bounds are taken from the axis limits of the current axes.
     |
     |      The line color or style is specified by:
     |
     |          - a  MATLAB-style linestyle like 'k--'
     |          - additional arguments passed to `Line2D <https://matplotlib.org/3.2.2/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D>`_
     |
     |      :seealso: :meth:`intersect_volume`
     |
     |  point(self, lam: 'Union[float, ArrayLike]') -> 'Points3'
     |      Generate point on line
     |
     |      :param lam: Scalar distance from principal point
     |      :type lam: float
     |      :return: Distance from principal point to the origin
     |      :rtype: float
     |
     |      ``line.point(λ)`` is a point on the line, where ``λ`` is the parametric
     |      distance along the line from the principal point of the line such
     |      that :math:`P = P_p + \lambda \hat{d}` and :math:`\hat{d}` is the line
     |      direction given by ``line.uw``.
     |
     |      :seealso: :meth:`pp` :meth:`closest` :meth:`uw` :meth:`lam`
     |
     |  side(self, other: 'Line3') -> 'float'
     |      Plucker side operator
     |
     |      :param other: second line
     |      :type other: Line3
     |      :return: permuted dot product
     |      :rtype: float
     |
     |      This permuted dot product operator is zero whenever the lines intersect or are parallel.
     |
     |  skew(self) -> 'R4x4'
     |      Line as a Plucker skew-symmetric matrix
     |
     |      :return: Skew-symmetric matrix form of Plucker coordinates
     |      :rtype: ndarray(4,4)
     |
     |      ``line.skew()`` is the Plucker matrix, a 4x4 skew-symmetric matrix
     |      representation of the line whose six unique elements are the
     |      Plucker coordinates of the line.
     |
     |      .. math::
     |
     |          \sk{L} = \begin{bmatrix} 0 & v_z & -v_y & \omega_x \\
     |              -v_z & 0 & v_x & \omega_y \\
     |              v_y & -v_x & 0 & \omega_z \\
     |              -\omega_x & -\omega_y & -\omega_z & 0 \end{bmatrix}
     |
     |      .. note::
     |
     |          - For two homogeneous points P and Q on the line, :math:`PQ^T-QP^T` is
     |          also skew symmetric.
     |          - The projection of Plucker line by a perspective camera is a
     |          homogeneous line (3x1) given by :math:`\vee C M C^T` where :math:`C
     |          \in \mathbf{R}^{3 \times 4}` is the camera matrix.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from Line3:
     |
     |  IntersectingPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
     |
     |  Join(P: 'ArrayLike3', Q: 'ArrayLike3') -> 'Self'
     |      Create 3D line from two 3D points
     |
     |      :param P: First 3D point
     |      :type P: array_like(3)
     |      :param Q: Second 3D point
     |      :type Q: array_like(3)
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``Line3.Join(P, Q)`` create a ``Line3`` object that represents
     |      the line joining the 3D points ``P`` (3,) and ``Q`` (3,). The direction
     |      is from ``Q`` to ``P``.
     |
     |      :seealso: :meth:`IntersectingPlanes` :meth:`PointDir`
     |
     |  PointDir(point: 'ArrayLike3', dir: 'ArrayLike3') -> 'Self'
     |      Create 3D line from a point and direction
     |
     |      :param point: A 3D point
     |      :type point: array_like(3)
     |      :param dir: Direction vector
     |      :type dir: array_like(3)
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``Line3.PointDir(P, W)`` is a `Line3`` object that represents the
     |      line containing the point ``P`` and parallel to the direction vector ``W``.
     |
     |      :seealso: :meth:`Join` :meth:`IntersectingPlanes`
     |
     |  TwoPlanes(pi1: 'Plane3', pi2: 'Plane3') -> 'Self'
     |      Create 3D line from intersection of two planes
     |
     |      :param pi1: First plane
     |      :type pi1: array_like(4), or ``Plane``
     |      :param pi2: Second plane
     |      :type pi2: array_like(4), or ``Plane``
     |      :return: 3D line
     |      :rtype: ``Line3`` instance
     |
     |      ``L = Line3.TwoPlanes(π1, π2)`` is a ``Line3`` object that represents
     |      the line formed by the intersection of two planes ``π1`` and ``π3``.
     |
     |      Planes are represented by the 4-vector :math:`[a, b, c, d]` which describes
     |      the plane :math:`\pi: ax + by + cz + d=0`.
     |
     |      :seealso: :meth:`Join` :meth:`PointDir`
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from Line3:
     |
     |  isvalid(x: 'NDArray', check: 'bool' = False) -> 'bool'
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from Line3:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  pp
     |      Principal point of the 3D line
     |
     |      :return: Principal point of the line
     |      :rtype: ndarray(3)
     |
     |      ``line.pp`` is the point on the line that is closest to the origin.
     |
     |      Notes:
     |
     |       - Same as Plucker.point(0)
     |
     |      :seealso: :meth:`ppd` :meth`point`
     |
     |  ppd
     |      Distance from principal point to the origin
     |
     |      :return: Distance from principal point to the origin
     |      :rtype: float
     |
     |      ``line.ppd`` is the distance from the principal point to the origin.
     |      This is the smallest distance of any point on the line
     |      to the origin.
     |
     |      :seealso: :meth:`pp`
     |
     |  shape
     |
     |  uw
     |      Line direction as a unit vector
     |
     |      :return: Line direction as a unit vector
     |      :rtype: ndarray(3,)
     |
     |      ``line.uw`` is a unit-vector parallel to the line.
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`w`
     |
     |  v
     |      Moment vector
     |
     |      :return: the moment vector
     |      :rtype: ndarray(3)
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`w`
     |
     |  vec
     |      Line as a Plucker coordinate vector
     |
     |      :return: Plucker coordinate vector
     |      :rtype: ndarray(6,)
     |
     |      ``line.vec`` is the  Plucker coordinate vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |  w
     |      Direction vector
     |
     |      :return: the direction vector
     |      :rtype: ndarray(3)
     |
     |      The line is represented by a vector :math:`(\vec{v}, \vec{w}) \in \mathbb{R}^6`.
     |
     |      :seealso: :meth:`v` :meth:`uw`
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from Line3:
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike4 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike6 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLikePure = typing.Union[typing.List[float], typing.Tuple[fl...nda...
    Callable = typing.Callable
        Deprecated alias to collections.abc.Callable.

        Callable[[int], str] signifies a function that takes a single
        parameter of type int and returns a str.

        The subscription syntax must always be used with exactly two
        values: the argument list and the return type.
        The argument list must be a list of types, a ParamSpec,
        Concatenate or ellipsis. The return type must be a single type.

        There is no syntax to indicate optional or keyword arguments;
        such function types are rarely used as callback types.

    Color = typing.Union[str, typing.List[float], typing.Tup...typing.Lite...
    DTypeLike = typing.Union[numpy.dtype[typing.Any], NoneType, ...e_like....
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    L = typing.Literal
        Special typing form to define literal types (a.k.a. value types).

        This form can be used to indicate to type checkers that the corresponding
        variable or function parameter has a value equivalent to the provided
        literal (or one of several literals)::

            def validate_simple(data: Any) -> Literal[True]:  # always returns True
                ...

            MODE = Literal['r', 'rb', 'w', 'wb']
            def open_helper(file: str, mode: MODE) -> str:
                ...

            open_helper('/some/path', 'r')  # Passes type check
            open_helper('/other/path', 'typo')  # Error in type checker

        Literal[...] cannot be subclassed. At runtime, an arbitrary value
        is allowed as type argument to Literal[...], but type checkers may
        impose restrictions.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Points3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    QuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy...
    R1 = numpy.ndarray[typing.Tuple[typing.Literal[1]], numpy.dtype[numpy....
    R1x1 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[1]...
    R1x2 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[2]...
    R1x3 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[3]...
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R2x1 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[1]...
    R2x2 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]...
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R3x1 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[1]...
    R3x3 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]...
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    R4x4 = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]...
    R6 = numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy....
    R6x6 = numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]...
    R8 = numpy.ndarray[typing.Tuple[typing.Literal[8]], numpy.dtype[numpy....
    R8x8 = numpy.ndarray[typing.Tuple[typing.Literal[8], typing.Literal[8]...
    RNx3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Rn = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.Literal...
    SE2Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SE3Array = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Litera...
    SEnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    SO2Array = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Litera...
    SO3Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SOnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Type = typing.Type
        Deprecated alias to builtins.type.

        builtins.type or typing.Type can be used to annotate class objects.
        For example, suppose we have the following classes::

            class User: ...  # Abstract base for User classes
            class BasicUser(User): ...
            class ProUser(User): ...
            class TeamUser(User): ...

        And a function that takes a class argument that's a subclass of
        User and returns an instance of the corresponding class::

            def new_user[U](user_class: Type[U]) -> U:
                user = user_class()
                # (Here we could write the user object to a database)
                return user

            joe = new_user(BasicUser)

        At this point the type checker knows that joe has type BasicUser.

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

    UnitQuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], n...
    se2Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    se3Array = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[...
    senArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    so2Array = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[...
    so3Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    sonArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\geom3d.py

spatialmath-python.importlib
Python Library Documentation: package importlib

NAME
    importlib - A pure Python implementation of import.

MODULE REFERENCE
    https://docs.python.org/3.12/library/importlib.html

    The following documentation is automatically generated from the Python
    source files.  It may be incomplete, incorrect or include features that
    are considered implementation detail and may vary between Python
    implementations.  When in doubt, consult the module reference at the
    location listed above.

PACKAGE CONTENTS
    _abc
    _bootstrap
    _bootstrap_external
    abc
    machinery
    metadata (package)
    readers
    resources (package)
    simple
    util

FUNCTIONS
    __import__(name, globals=None, locals=None, fromlist=(), level=0)
        Import a module.

        The 'globals' argument is used to infer where the import is occurring from
        to handle relative imports. The 'locals' argument is ignored. The
        'fromlist' argument specifies what should exist as attributes on the module
        being imported (e.g. ``from module import <fromlist>``).  The 'level'
        argument represents the package location to import from in a relative
        import (e.g. ``from ..pkg import mod`` would have a 'level' of 2).

    import_module(name, package=None)
        Import a module.

        The 'package' argument is required when performing a relative import. It
        specifies the package to use as the anchor point from which to resolve the
        relative import to an absolute import.

    invalidate_caches()
        Call the invalidate_caches() method on all meta path finders stored in
        sys.meta_path (where implemented).

    reload(module)
        Reload the module and return it.

        The module must have been successfully imported before.

DATA
    __all__ = ['__import__', 'import_module', 'invalidate_caches', 'reload...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\importlib\__init__.py

spatialmath-python.pose2d
Python Library Documentation: module spatialmath.pose2d in spatialmath

NAME
    spatialmath.pose2d - Classes to abstract 2D pose and orientation using matrices in SE(2) and SO(2)

DESCRIPTION
    To use::

        from spatialmath.pose2d import *
        T = SE2(1, 2, 0.3)

        import spatialmath as sm
        T = sm.SE2.Rx(1, 2, 0.3)


     .. inheritance-diagram:: spatialmath.pose3d
        :top-classes: collections.UserList
        :parts: 1

CLASSES
    spatialmath.baseposematrix.BasePoseMatrix(spatialmath.baseposelist.BasePoseList)
        SO2
            SE2

    class SE2(SO2)
     |  SE2(x=None, y=None, theta=None, *, unit='rad', check=True)
     |
     |     SE(2) matrix class
     |
     |     This subclass represents rigid-body motion (pose) in 2D space.  Internally
     |     it is a 3x3 homogeneous transformation matrix belonging to the group SE(2).
     |
     |  .. inheritance-diagram:: spatialmath.pose2d.SE2
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  Method resolution order:
     |      SE2
     |      SO2
     |      spatialmath.baseposematrix.BasePoseMatrix
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  SE3(self, z=0)
     |      Create SE(3) from SE(2)
     |
     |      :param z: default z coordinate, defaults to 0
     |      :type z: float
     |      :return: SE(2) with same rotation but zero translation
     |      :rtype: SE2 instance
     |
     |      "Lifts" 2D rigid-body motion to 3D, rotation in the xy-plane (about the z-axis) and
     |      z-coordinate is settable.
     |
     |  Twist2(self)
     |
     |  __init__(self, x=None, y=None, theta=None, *, unit='rad', check=True)
     |      Construct new SE(2) object
     |
     |      :param unit: angular units 'deg' or 'rad' [default] if applicable
     |      :type unit: str, optional
     |      :param check: check for valid SE(2) elements if applicable, default to True
     |      :type check: bool
     |      :return: SE(2) matrix
     |      :rtype: SE2 instance
     |
     |      - ``SE2()`` is an SE2 instance representing a null motion -- the
     |        identity matrix
     |      - ``SE2(θ)`` is an SE2 instance representing a pure rotation of
     |        ``θ`` radians
     |      - ``SE2(θ, unit='deg')`` as above but ``θ`` in degrees
     |      - ``SE2(x, y)`` is an SE2 instance representing a pure translation of
     |        (``x``, ``y``)
     |      - ``SE2(t)`` is an SE2 instance representing a pure translation of
     |        (``x``, ``y``) where``t``=[x,y] is a 2-element array_like
     |      - ``SE2(x, y, θ)`` is an SE2 instance representing a translation of
     |        (``x``, ``y``) and a rotation of ``θ`` radians
     |      - ``SE2(x, y, θ, unit='deg')`` as above but ``θ`` in degrees
     |      - ``SE2(t)`` where ``t``=[x,y] is a 2-element array_like, is an SE2
     |        instance representing a pure translation of (``x``, ``y``)
     |      - ``SE2(q)`` where ``q``=[x,y,θ] is a 3-element array_like, is an SE2
     |        instance representing a translation of (``x``, ``y``) and a rotation
     |        of ``θ`` radians
     |      - ``SE2(t, unit='deg')`` as above but ``θ`` in degrees
     |      - ``SE2(T)`` is an SE2 instance with rigid-body motion described by the
     |        SE(2) matrix T which is a 3x3 numpy array.  If ``check`` is ``True``
     |        check the matrix belongs to SE(2).
     |      - ``SE2([T1, T2, ... TN])`` is an SE2 instance containing a sequence of
     |        N rigid-body motions, each described by an SE(2) matrix Ti which is a
     |        3x3 numpy array. If ``check`` is ``True`` then check each matrix
     |        belongs to SE(2).
     |      - ``SE2([X1, X2, ... XN])`` is an SE2 instance containing a sequence of
     |        N rigid-body motions, where each Xi is an SE2 instance.
     |
     |  inv(self)
     |      Inverse of SE(2)
     |
     |      :param self: pose
     |      :type self: SE2 instance
     |      :return: inverse
     |      :rtype: SE2
     |
     |      Notes:
     |
     |          - for elements of SE(2) this takes into account the matrix structure :math:`T = \left[ \begin{array}{cc} R & t \\ 0 & 1 \end{array} \right], T^{-1} = \left[ \begin{array}{cc} R^T & -R^T t \\ 0 & 1 \end{array} \right]`
     |          - if `x` contains a sequence, returns an `SE2` with a sequence of inverses
     |
     |  xyt(self)
     |      SE(2) as a configuration vector
     |
     |      :return: An array :math:`[x, y, \theta]` :rtype: numpy.ndarray
     |
     |      ``x.xyt`` is the rigidbody motion in minimal form as a translation and
     |      rotation expressed in vector form as :math:`[x, y, \theta]`.  If
     |      ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return an ndarray with shape=(N,3)
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  Exp(S, check=True)
     |      Construct a new SE(2) from se(2) Lie algebra
     |
     |      :param S: element of Lie algebra se(2)
     |      :type S: numpy ndarray
     |      :param check: check that passed matrix is valid se(2), default True
     |      :type check: bool
     |      :return: homogeneous transform matrix
     |      :rtype: SE2 instance
     |
     |      - ``SE2.Exp(S)`` is an SE(2) rotation defined by its Lie algebra
     |        which is a 3x3 se(2) matrix (skew symmetric)
     |      - ``SE2.Exp(t)`` is an SE(2) rotation defined by a 3-element twist
     |        vector array_like (the unique elements of the se(2) skew-symmetric matrix)
     |      - ``SE2.Exp(T)`` is a sequence of SE(2) rigid-body motions defined by an Nx3 matrix of twist vectors, one per row.
     |
     |      Note:
     |
     |      - an input 3x3 matrix is ambiguous, it could be the first or third case above. In this case the argument ``se2`` is the decider.
     |
     |      :seealso: :func:`spatialmath.base.transforms2d.trexp`, :func:`spatialmath.base.transformsNd.skew`
     |
     |  Rand(N=1, xrange=(-1, 1), yrange=(-1, 1), arange=(0, 6.283185307179586), unit='rad')
     |      Construct a new random SE(2)
     |
     |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
     |      :type xrange: 2-element sequence, optional
     |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
     |      :type yrange: 2-element sequence, optional
     |      :param arange: angle range [min,max], defaults to :math:`[0, 2\pi)`
     |      :type arange: 2-element sequence, optional
     |      :param N: number of random rotations, defaults to 1
     |      :type N: int
     |      :param unit: angular units 'deg' or 'rad' [default] if applicable
     |      :type unit: str, optional
     |      :return: homogeneous rigid-body transformation matrix
     |      :rtype: SE2 instance
     |
     |      Return an SE2 instance with random rotation and translation.
     |
     |      - ``SE2.Rand()`` is a random SE(2) rotation.
     |      - ``SE2.Rand(N)`` is an SE2 object containing a sequence of N random
     |        poses.
     |
     |      Example, create random ten vehicles in the xy-plane::
     |
     |          >>> x = SE3.Rand(N=10, xrange=[-2,2], yrange=[-2,2])
     |          >>> len(x)
     |          10
     |
     |  Rot(theta, unit='rad')
     |      Create an SE(2) rotation
     |
     |      :param theta: rotation angle in radians
     |      :type theta: float
     |      :param unit: angular units: "rad" [default] or "deg"
     |      :type unit: str
     |      :return: SE(2) matrix
     |      :rtype: SE2 instance
     |
     |      `SE2.Rot(theta)` is an SE(2) rotation of ``theta``
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> SE2.Rot(0.3)
     |          >>> SE2.Rot([0.2, 0.3])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Tx(x)
     |      Create an SE(2) translation along the X-axis
     |
     |      :param x: translation distance along the X-axis
     |      :type x: float
     |      :return: SE(2) matrix
     |      :rtype: SE2 instance
     |
     |      `SE2.Tx(x)` is an SE(2) translation of ``x`` along the x-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> SE2.Tx(2)
     |          >>> SE2.Tx([2,3])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Ty(y)
     |      Create an SE(2) translation along the Y-axis
     |
     |      :param y: translation distance along the Y-axis
     |      :type y: float
     |      :return: SE(2) matrix
     |      :rtype: SE2 instance
     |
     |      `SE2.Ty(y) is an SE(2) translation of ``y`` along the y-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> SE2.Ty(2)
     |          >>> SE2.Ty([2,3])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x, check=True)
     |      Test if matrix is valid SE(2)
     |
     |      :param x: matrix to test
     |      :type x: numpy.ndarray
     |      :return: true if the matrix is a valid element of SE(2), ie. it is a
     |               3x3 homogeneous rigid-body transformation matrix.
     |      :rtype: bool
     |
     |      :seealso: :func:`~spatialmath.base.transform2d.ishom`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (3,3)
     |      :rtype: tuple
     |
     |  t
     |      Translational component of SE(2)
     |
     |      :param self: SE(2)
     |      :type self: SE2 instance
     |      :return: translational component
     |      :rtype: numpy.ndarray
     |
     |      ``x.t`` is the translational vector component.  If ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(2,)
     |      - N>1, return an ndarray with shape=(N,2)
     |
     |  x
     |      First element of the translational component of SE(2)
     |
     |      :param self: SE(2)
     |      :type self: SE2 instance
     |      :return: translational component
     |      :rtype: float
     |
     |      ``v.x`` is the first element of the translational vector component.  If ``len(x)`` is:
     |
     |      - 1, return an float
     |      - N>1, return an ndarray with shape=(N,)
     |
     |  y
     |      Second element of the translational component of SE(2)
     |
     |      :param self: SE(2)
     |      :type self: SE2 instance
     |      :return: translational component
     |      :rtype: float
     |
     |      ``v.y`` is the second element of the translational vector component.  If ``len(x)`` is:
     |
     |      - 1, return an float
     |      - N>1, return an ndarray with shape=(N,)
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SO2:
     |
     |  SE2(self)
     |      Create SE(2) from SO(2)
     |
     |      :return: SE(2) with same rotation but zero translation
     |      :rtype: SE2 instance
     |
     |  theta(self, unit='rad')
     |      SO(2) as a rotation angle
     |
     |      :param unit: angular units 'deg' or 'rad' [default]
     |      :type unit: str, optional
     |      :return: rotation angle
     |      :rtype: float or list
     |
     |      ``x.theta`` is the rotation angle such that `x` is `SO2(x.theta)`.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SO2:
     |
     |  R
     |      SO(2) or SE(2) as rotation matrix
     |
     |      :return: rotational component
     |      :rtype: numpy.ndarray, shape=(2,2)
     |
     |      ``x.R`` returns the rotation matrix, when `x` is `SO2` or `SE2`. If `len(x)` is:
     |
     |      - 1, return an ndarray with shape=(2,2)
     |      - N>1, return ndarray with shape=(N,2,2)
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __add__(left, right)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Add the elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
     |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
     |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ========================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ========================
     |      Pose             Pose             NxN matrix   element-wise matrix sum
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ========================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar + Pose is handled by :meth:`__radd__`
     |          #. Addition is commutative
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose addition either or both operands may hold more than one value which
     |      results in the sum holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``sum = left + right``
     |       1          M             M    ``sum[i] = left + right[i]``
     |       N          1             M    ``sum[i] = left[i] + right``
     |       M          M             M    ``sum[i] = left[i] + right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __eq__(left, right: 'Self') -> 'bool'
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for equality
     |
     |      ``X == Y`` is true of the poses are of the same type and numerically
     |      equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the equality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``eq = left == right``
     |       1          M             M    ``eq[i] = left == right[i]``
     |       N          1             M    ``eq[i] = left[i] == right``
     |       M          M             M    ``eq[i] = left[i] == right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __iadd__(left, right)
     |      Overloaded ``+=`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
     |      - ``X += s`` elementwise addition of the matrix elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__add__``
     |
     |  __imul__(left, right)
     |      Overloaded ``*=`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
     |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__mul__``
     |
     |  __isub__(left, right: 'Self')
     |      Overloaded ``-=`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises: ValueError
     |
     |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
     |        and ``Y`` and places the result in ``X``
     |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
     |        and the scalar ``s`` and places the result in ``X``
     |
     |      :seealso: ``__sub__``
     |
     |  __itruediv__(left, right)
     |      Overloaded ``/=`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
     |      - ``X /= s`` performs elementwise division of the elements of ``X``
     |        by ``s`` and places the result in ``X``
     |
     |      :seealso: ``__truediv__``
     |
     |  __matmul__(left, right)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :return: Product of two operands with normalization
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
     |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
     |        and places the result in ``X``
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally
     |          update over many cycles.
     |
     |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Pose composition, scaling or vector transformation:
     |
     |      - ``X * Y`` compounds the poses ``X`` and ``Y``
     |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
     |
     |      ==============   ==============   ===========  ======================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ======================
     |      Pose             Pose             Pose         matrix product
     |      Pose             scalar           NxN matrix   element-wise product
     |      scalar           Pose             NxN matrix   element-wise product
     |      Pose             N-vector         N-vector     vector transform
     |      Pose             NxM matrix       NxM matrix   transform each column
     |      ==============   ==============   ===========  ======================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar x Pose is handled by __rmul__`
     |          #. Scalar multiplication is commutative but the result is not a group
     |             operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
     |          SE3(array([[0., 0., 1., 0.],
     |                  [1., 0., 0., 0.],
     |                  [0., 1., 0., 0.],
     |                  [0., 0., 0., 1.]]))
     |          >>> SE3.Rx(pi/2) * 2
     |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
     |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
     |
     |      For vector transformation there are three cases:
     |
     |      =========  ===========  =====  ==========================
     |            Multiplicands             Product
     |      ----------------------  ---------------------------------
     |      len(left)  right.shape  shape  operation
     |      =========  ===========  =====  ==========================
     |      1          (N,)         (N,)   vector transformation
     |      M          (N,)         (N,M)  vector transformations
     |      1          (N,M)        (N,M)  column transformation
     |      =========  ===========  =====  ==========================
     |
     |      .. note::
     |          - The vector is an array-like, a 1D NumPy array or a list/tuple
     |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
     |            form, transformed, then converted back to Euclidean form.
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * [0, 1, 0]
     |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
     |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
     |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :return: Inequality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for inequality
     |
     |      - ``X != Y`` is true of the poses are of the same type but not numerically
     |        equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the inequality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``ne = left != right``
     |       1          M             M    ``ne[i] = left != right[i]``
     |       N          1             M    ``ne[i] = left[i] != right``
     |       M          M             M    ``ne[i] = left[i] != right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __pow__(self, n: 'int') -> 'Self'
     |      Overloaded ``**`` operator (superclass method)
     |
     |      :param n: exponent
     |      :type n: int
     |      :return: pose to the power ``n``
     |      :rtype: pose instance
     |
     |      ``X**n`` raise all values held in `X` to the specified power using repeated
     |      multiplication.  If ``n`` < 0 then the result is inverted.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.1) ** 2
     |          >>> SE3.Rx([0, 0.1]) ** 2
     |
     |  __radd__(right, left)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__add__`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> repr(x)
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Left-multiplication
     |
     |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
     |        elements of ``X`` by ``s`` and the result is a NumPy array.
     |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
     |        of ``A`` and ``X`` and the result is a NumPy array.
     |
     |      :seealso: :func:`__mul__`
     |
     |  __rsub__(right, left: 'Self')
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__sub__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of pose (superclass method)
     |
     |      :return: readable representation of the pose
     |      :rtype: str
     |
     |      Convert the pose's matrix value to a simple grid of numbers.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x)
     |
     |      Notes:
     |
     |          - By default, the output is colorised for an ANSI terminal console:
     |
     |              * red: rotational elements
     |              * blue: translational elements
     |              * white: constant elements
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Subtract elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
     |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
     |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ==============================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ==============================
     |      Pose             Pose             NxN matrix   element-wise matrix difference
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ==============================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar - Pose is handled by :meth:`__rsub__`
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose subtraction either or both operands may hold more than one value which
     |      results in the difference holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``diff = left - right``
     |       1          M             M    ``diff[i] = left - right[i]``
     |       N          1             M    ``diff[i] = left[i] - right``
     |       M          M             M    ``diff[i] = left[i]  right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __truediv__(left, right)
     |      Overloaded ``/`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      Pose composition or scaling:
     |
     |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
     |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
     |
     |      ==============   ==============   ===========  =========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   --------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  =========================
     |      Pose             Pose             Pose         matrix product by inverse
     |      Pose             scalar           NxN matrix   element-wise division
     |      ==============   ==============   ===========  =========================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar multiplication is not a group operation so the result will
     |             be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |  animate(self, *args, start=None, **kwargs) -> 'None'
     |      Plot pose object as an animated coordinate frame (superclass method)
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: same as ``self``
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
     |        from the origin in either 2D or 3D.  There are many options, see the
     |        links below.
     |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
     |        frame moving from pose ``X1``, in either 2D or 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=SE3.Ry(0.2))
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
     |
     |  conjugation(self, A: 'NDArray') -> 'NDArray'
     |      Matrix conjugation
     |
     |      :param A: matrix to conjugate
     |      :type A: ndarray
     |      :return: conjugated matrix
     |      :rtype: ndarray
     |
     |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
     |      is the current object.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO2
     |          >>> import numpy as np
     |          >>> R = SO2(0.5)
     |          >>> A = np.array([[10, 0], [0, 1]])
     |          >>> print(R * A * R.inv())
     |          >>> print(R.conjugation(A))
     |
     |  det(self) -> 'Tuple[float, Rn]'
     |      Determinant of rotational component (superclass method)
     |
     |      :return: Determinant of rotational component
     |      :rtype: float or NumPy array
     |
     |      ``x.det()`` is the determinant of the rotation component of the values
     |      of ``x``.
     |
     |      Example::
     |
     |          >>> x=SE3.Rand()
     |          >>> x.det()
     |          1.0000000000000004
     |          >>> x=SE3.Rand(N=2)
     |          >>> x.det()
     |          [0.9999999999999997, 1.0000000000000002]
     |
     |      :SymPy: not supported
     |
     |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
     |      Interpolate between poses (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :param shortest: take the shortest path along the great circle for the rotation
     |      :type shortest: bool, default to True
     |      :return: interpolated pose
     |      :rtype: same as ``self``
     |
     |      - ``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.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
     |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
     |          >>> x.interp(y, 0)    # this is x
     |          >>> x.interp(y, 1)    # this is y
     |          >>> x.interp(y, 0.5)  # this is in between
     |          >>> z = x.interp(y, 11)  # in 11 steps
     |          >>> len(z)
     |          >>> z[0]              # this is x
     |          >>> z[5]              # this is in between
     |
     |      .. note::
     |
     |          - 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
     |
     |  interp1(self, s: 'float' = None) -> 'Self'
     |      Interpolate pose (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1
     |      :type s: array_like
     |      :return: interpolated pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
     |
     |          ======  ======  ===========  ===============================
     |          len(X)  len(s)  len(result)  Result
     |          ======  ======  ===========  ===============================
     |          1       1       1            Y = interp(X, s)
     |          M       1       M            Y[i] = interp(X[i], s)
     |          1       M       M            Y[i] = interp(X, s[i])
     |          ======  ======  ===========  ===============================
     |
     |      Example::
     |
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x.interp(0))
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |          >>> print(x.interp(1))
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
     |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |          >>> y = x.interp(x, np.linspace(0, 1, 10))
     |          >>> len(y)
     |          10
     |          >>> y[5]
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
     |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |
     |      Notes:
     |
     |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
     |
     |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
     |
     |      :SymPy: not supported
     |
     |  ishom(self) -> 'bool'
     |      Test if object belongs to SE(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          True
     |
     |  ishom2(self) -> 'bool'
     |      Test if object belongs to SE(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          True
     |
     |  isrot(self) -> 'bool'
     |      Test if object belongs to SO(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          False
     |
     |  isrot2(self) -> 'bool'
     |      Test if object belongs to SO(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          False
     |
     |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
     |      Logarithm of pose (superclass method)
     |
     |      :return: logarithm
     |      :rtype: ndarray
     |      :raises: ValueError
     |
     |      An efficient closed-form solution of the matrix logarithm.
     |
     |      =====  ======  ===============================
     |      Input         Output
     |      -----  ---------------------------------------
     |      Pose   Shape   Structure
     |      =====  ======  ===============================
     |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
     |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
     |      =====  ======  ===============================
     |
     |      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. ]])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
     |      :func:`~spatialmath.base.transforms3d.trlog`
     |
     |      :SymPy: not supported
     |
     |  norm(self) -> 'Self'
     |      Normalize pose (superclass method)
     |
     |      :return: pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
     |        part of all values has been adjusted to ensure it is a proper orthogonal
     |        matrix rotation.
     |
     |      Example::
     |
     |          >>> x = SE3()
     |          >>> y = x.norm()
     |          >>> y
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |
     |      Notes:
     |
     |      #. Only the direction of A vector (the z-axis) is unchanged.
     |      #. Used to prevent finite word length arithmetic causing transforms to
     |         become 'unnormalized'.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
     |
     |  plot(self, *args, **kwargs) -> 'None'
     |      Plot pose object as a coordinate frame (superclass method)
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
     |        2D or 3D.  There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.plot(frame='A', color='green')
     |
     |      .. plot::
     |
     |          from spatialmath import SE3
     |          X = SE3.Rx(0.3)
     |          X.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
     |
     |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
     |      Print pose as a matrix (superclass method)
     |
     |      :param label: label to print before the matrix, defaults to None
     |      :type label: str, optional
     |      :param file: file to write to, defaults to None
     |      :type file: file object, optional
     |
     |      Print the pose as a matrix, with an optional line beforehand.  By default
     |      the matrix is printed to stdout.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3().print()
     |          >>> SE3().print("pose is:")
     |
     |      :seealso: :meth:`printline` :meth:`strline`
     |
     |  printline(self, *args, **kwargs) -> 'None'
     |      Print pose in compact single line format (superclass method)
     |
     |      :param arg: value for orient option, optional
     |      :type arg: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param file: file to write formatted string to. [default, stdout]
     |      :type file: file object
     |
     |      Print pose in a compact single line format. If ``X`` has multiple
     |      values, print one per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.printline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.printline()
     |          >>> x.printline('angvec')
     |          >>> x.printline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.printline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
     |
     |  prod(self, norm=False, check=True) -> 'Self'
     |      Product of elements (superclass method)
     |
     |      :param norm: normalize the product, defaults to False
     |      :type norm: bool, optional
     |      :param check: check that computed matrix is valid member of group, default True
     |      :bool check: bool, optional
     |      :return: Product of elements
     |      :rtype: pose instance
     |
     |      ``x.prod()`` is the product of the values held by ``x``, ie.
     |      :math:`\prod_i^N T_i`.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
     |          >>> x.prod()
     |
     |      .. note:: When compounding many transformations the product may become
     |          denormalized resulting in a result that is not a proper member of the
     |          group.  You can either disable membership checking by ``check=False``
     |          which is risky, or normalize the result by ``norm=True``.
     |
     |  simplify(self) -> 'Self'
     |      Symbolically simplify matrix values (superclass method)
     |
     |      :return: pose with symbolic elements
     |      :rtype: pose instance
     |
     |      Apply symbolic simplification to every element of every value in the
     |      pose instance.
     |
     |      Example::
     |
     |          >>> a = SE3.Rx(sympy.symbols('theta'))
     |          >>> b = a * a
     |          >>> b
     |          SE3(array([[1, 0, 0, 0.0],
     |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
     |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
     |          [0.0, 0, 0, 1.0]], dtype=object)
     |          >>> b.simplify()
     |          SE3(array([[1, 0, 0, 0],
     |          [0, cos(2*theta), -sin(2*theta), 0],
     |          [0, sin(2*theta), cos(2*theta), 0],
     |          [0, 0, 0, 1.00000000000000]], dtype=object))
     |
     |      .. todo:: No need to simplify the constants in bottom row
     |
     |      :SymPy: supported
     |
     |  stack(self) -> 'NDArray'
     |      Convert to 3-dimensional matrix
     |
     |      :return: 3-dimensional NumPy array
     |      :rtype: ndarray(n,n,m)
     |
     |      Converts the value to a 3-dimensional NumPy array where the values are
     |      stacked along the third axis.  The first two dimensions are given by
     |      ``self.shape``.
     |
     |  strline(self, *args, **kwargs) -> 'str'
     |      Convert pose to compact single line string (superclass method)
     |
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: pose in string format
     |      :rtype: str
     |
     |      Convert pose in a compact single line format. If ``X`` has multiple
     |      values, the string has one pose per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.strline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.strline()
     |          >>> x.strline('angvec')
     |          >>> x.strline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.strline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __new__(cls, *args, **kwargs)
     |      Create the subclass instance (superclass method)
     |
     |      Create a new instance and call the superclass initializer to enable the
     |      ``UserList`` capabilities.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  N
     |      Dimension of the object's group (superclass property)
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
     |      This corresponds to the dimension of the space, 2D or 3D, to which these
     |      rotations or rigid-body motions apply.
     |
     |      Example::
     |
     |          >>> SE3().N
     |          3
     |          >>> SE2().N
     |          2
     |
     |  about
     |      Succinct summary of object type and length (superclass property)
     |
     |      :return: succinct summary
     |      :rtype: str
     |
     |      Displays the type and the number of elements in compact form, for
     |      example::
     |
     |          >>> x = SE3([SE3() for i in range(20)])
     |          >>> len(x)
     |          20
     |          >>> print(x.about)
     |          SE3[20]
     |
     |  isSE
     |      Test if object belongs to SE(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SE2 or SE3
     |      :rtype: bool
     |
     |  isSO
     |      Test if object belongs to SO(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SO2 or SO3
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __len__(self)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SO2(spatialmath.baseposematrix.BasePoseMatrix)
     |  SO2(arg=None, *, unit='rad', check=True)
     |
     |  SO(2) matrix class
     |
     |  This subclass represents rotations in 2D space.  Internally it is a 2x2 orthogonal matrix belonging
     |  to the group SO(2).
     |
     |  .. inheritance-diagram:: spatialmath.pose2d.SO2
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  Method resolution order:
     |      SO2
     |      spatialmath.baseposematrix.BasePoseMatrix
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  SE2(self)
     |      Create SE(2) from SO(2)
     |
     |      :return: SE(2) with same rotation but zero translation
     |      :rtype: SE2 instance
     |
     |  __init__(self, arg=None, *, unit='rad', check=True)
     |      Construct new SO(2) object
     |
     |      :param unit: angular units 'deg' or 'rad' [default] if applicable
     |      :type unit: str, optional
     |      :param check: check for valid SO(2) elements if applicable, default to True
     |      :type check: bool
     |      :return: SO(2) rotation
     |      :rtype: SO2 instance
     |
     |      - ``SO2()`` is an SO2 instance representing a null rotation -- the identity matrix.
     |      - ``SO2(θ)`` is an SO2 instance representing a rotation by ``θ`` radians.  If ``θ`` is array_like
     |        `[θ1, θ2, ... θN]` then an SO2 instance containing a sequence of N rotations.
     |      - ``SO2(θ, unit='deg')`` is an SO2 instance representing a rotation by ``θ`` degrees.  If ``θ`` is array_like
     |        `[θ1, θ2, ... θN]` then an SO2 instance containing a sequence of N rotations.
     |      - ``SO2(R)`` is an SO2 instance with rotation described by the SO(2) matrix R which is a 2x2 numpy array.  If ``check``
     |        is ``True`` check the matrix belongs to SO(2).
     |      - ``SO2([R1, R2, ... RN])`` is an SO2 instance containing a sequence of N rotations, each described by an SO(2) matrix
     |        Ri which is a 2x2 numpy array. If ``check`` is ``True`` then check each matrix belongs to SO(2).
     |      - ``SO2([X1, X2, ... XN])`` is an SO2 instance containing a sequence of N rotations, where each Xi is an SO2 instance.
     |
     |  inv(self)
     |      Inverse of SO(2)
     |
     |      :return: inverse rotation
     |      :rtype: SO2 instance
     |
     |      - ``x.inv()`` is the inverse of `x`.
     |
     |      Notes:
     |
     |          - for elements of SO(2) this is the transpose.
     |          - if `x` contains a sequence, returns an `SO2` with a sequence of inverses
     |
     |  theta(self, unit='rad')
     |      SO(2) as a rotation angle
     |
     |      :param unit: angular units 'deg' or 'rad' [default]
     |      :type unit: str, optional
     |      :return: rotation angle
     |      :rtype: float or list
     |
     |      ``x.theta`` is the rotation angle such that `x` is `SO2(x.theta)`.
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  Exp(S, check=True)
     |      Construct new SO(2) rotation matrix from so(2) Lie algebra
     |
     |      :param S: element of Lie algebra so(2)
     |      :type S: numpy ndarray
     |      :param check: check that passed matrix is valid so(2), default True
     |      :type check: bool
     |      :return: SO(2) rotation matrix
     |      :rtype: SO2 instance
     |
     |      - ``SO2.Exp(S)`` is an SO(2) rotation defined by its Lie algebra
     |        which is a 2x2 so(2) matrix (skew symmetric)
     |
     |      :seealso: :func:`spatialmath.base.transforms2d.trexp`, :func:`spatialmath.base.transformsNd.skew`
     |
     |  Rand(N=1, arange=(0, 6.283185307179586), unit='rad')
     |      Construct new SO(2) with random rotation
     |
     |      :param arange: rotation range, defaults to :math:`[0, 2\pi)`.
     |      :type arange: 2-element array-like, optional
     |      :param unit: angular units as 'deg or 'rad' [default]
     |      :type unit: str, optional
     |      :param N: number of random rotations, defaults to 1
     |      :type N: int
     |      :return: SO(2) rotation matrix
     |      :rtype: SO2 instance
     |
     |      - ``SO2.Rand()`` is a random SO(2) rotation.
     |      - ``SO2.Rand([-90, 90], unit='deg')`` is a random SO(2) rotation between
     |        -90 and +90 degrees.
     |      - ``SO2.Rand(N)`` is a sequence of N random rotations.
     |
     |      Rotations are uniform over the specified interval.
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x, check=True)
     |      Test if matrix is valid SO(2)
     |
     |      :param x: matrix to test
     |      :type x: numpy.ndarray
     |      :return: True if the matrix is a valid element of SO(2), ie. it is a 2x2
     |          orthonormal matrix with determinant of +1.
     |      :rtype: bool
     |
     |      :seealso: :func:`~spatialmath.base.transform3d.isrot`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  R
     |      SO(2) or SE(2) as rotation matrix
     |
     |      :return: rotational component
     |      :rtype: numpy.ndarray, shape=(2,2)
     |
     |      ``x.R`` returns the rotation matrix, when `x` is `SO2` or `SE2`. If `len(x)` is:
     |
     |      - 1, return an ndarray with shape=(2,2)
     |      - N>1, return ndarray with shape=(N,2,2)
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (2,2)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __add__(left, right)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Add the elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
     |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
     |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ========================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ========================
     |      Pose             Pose             NxN matrix   element-wise matrix sum
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ========================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar + Pose is handled by :meth:`__radd__`
     |          #. Addition is commutative
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose addition either or both operands may hold more than one value which
     |      results in the sum holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``sum = left + right``
     |       1          M             M    ``sum[i] = left + right[i]``
     |       N          1             M    ``sum[i] = left[i] + right``
     |       M          M             M    ``sum[i] = left[i] + right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __eq__(left, right: 'Self') -> 'bool'
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for equality
     |
     |      ``X == Y`` is true of the poses are of the same type and numerically
     |      equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the equality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``eq = left == right``
     |       1          M             M    ``eq[i] = left == right[i]``
     |       N          1             M    ``eq[i] = left[i] == right``
     |       M          M             M    ``eq[i] = left[i] == right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __iadd__(left, right)
     |      Overloaded ``+=`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
     |      - ``X += s`` elementwise addition of the matrix elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__add__``
     |
     |  __imul__(left, right)
     |      Overloaded ``*=`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
     |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__mul__``
     |
     |  __isub__(left, right: 'Self')
     |      Overloaded ``-=`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises: ValueError
     |
     |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
     |        and ``Y`` and places the result in ``X``
     |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
     |        and the scalar ``s`` and places the result in ``X``
     |
     |      :seealso: ``__sub__``
     |
     |  __itruediv__(left, right)
     |      Overloaded ``/=`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
     |      - ``X /= s`` performs elementwise division of the elements of ``X``
     |        by ``s`` and places the result in ``X``
     |
     |      :seealso: ``__truediv__``
     |
     |  __matmul__(left, right)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :return: Product of two operands with normalization
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
     |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
     |        and places the result in ``X``
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally
     |          update over many cycles.
     |
     |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Pose composition, scaling or vector transformation:
     |
     |      - ``X * Y`` compounds the poses ``X`` and ``Y``
     |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
     |
     |      ==============   ==============   ===========  ======================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ======================
     |      Pose             Pose             Pose         matrix product
     |      Pose             scalar           NxN matrix   element-wise product
     |      scalar           Pose             NxN matrix   element-wise product
     |      Pose             N-vector         N-vector     vector transform
     |      Pose             NxM matrix       NxM matrix   transform each column
     |      ==============   ==============   ===========  ======================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar x Pose is handled by __rmul__`
     |          #. Scalar multiplication is commutative but the result is not a group
     |             operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
     |          SE3(array([[0., 0., 1., 0.],
     |                  [1., 0., 0., 0.],
     |                  [0., 1., 0., 0.],
     |                  [0., 0., 0., 1.]]))
     |          >>> SE3.Rx(pi/2) * 2
     |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
     |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
     |
     |      For vector transformation there are three cases:
     |
     |      =========  ===========  =====  ==========================
     |            Multiplicands             Product
     |      ----------------------  ---------------------------------
     |      len(left)  right.shape  shape  operation
     |      =========  ===========  =====  ==========================
     |      1          (N,)         (N,)   vector transformation
     |      M          (N,)         (N,M)  vector transformations
     |      1          (N,M)        (N,M)  column transformation
     |      =========  ===========  =====  ==========================
     |
     |      .. note::
     |          - The vector is an array-like, a 1D NumPy array or a list/tuple
     |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
     |            form, transformed, then converted back to Euclidean form.
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * [0, 1, 0]
     |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
     |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
     |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :return: Inequality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for inequality
     |
     |      - ``X != Y`` is true of the poses are of the same type but not numerically
     |        equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the inequality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``ne = left != right``
     |       1          M             M    ``ne[i] = left != right[i]``
     |       N          1             M    ``ne[i] = left[i] != right``
     |       M          M             M    ``ne[i] = left[i] != right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __pow__(self, n: 'int') -> 'Self'
     |      Overloaded ``**`` operator (superclass method)
     |
     |      :param n: exponent
     |      :type n: int
     |      :return: pose to the power ``n``
     |      :rtype: pose instance
     |
     |      ``X**n`` raise all values held in `X` to the specified power using repeated
     |      multiplication.  If ``n`` < 0 then the result is inverted.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.1) ** 2
     |          >>> SE3.Rx([0, 0.1]) ** 2
     |
     |  __radd__(right, left)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__add__`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> repr(x)
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Left-multiplication
     |
     |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
     |        elements of ``X`` by ``s`` and the result is a NumPy array.
     |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
     |        of ``A`` and ``X`` and the result is a NumPy array.
     |
     |      :seealso: :func:`__mul__`
     |
     |  __rsub__(right, left: 'Self')
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__sub__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of pose (superclass method)
     |
     |      :return: readable representation of the pose
     |      :rtype: str
     |
     |      Convert the pose's matrix value to a simple grid of numbers.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x)
     |
     |      Notes:
     |
     |          - By default, the output is colorised for an ANSI terminal console:
     |
     |              * red: rotational elements
     |              * blue: translational elements
     |              * white: constant elements
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Subtract elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
     |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
     |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ==============================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ==============================
     |      Pose             Pose             NxN matrix   element-wise matrix difference
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ==============================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar - Pose is handled by :meth:`__rsub__`
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose subtraction either or both operands may hold more than one value which
     |      results in the difference holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``diff = left - right``
     |       1          M             M    ``diff[i] = left - right[i]``
     |       N          1             M    ``diff[i] = left[i] - right``
     |       M          M             M    ``diff[i] = left[i]  right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __truediv__(left, right)
     |      Overloaded ``/`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      Pose composition or scaling:
     |
     |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
     |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
     |
     |      ==============   ==============   ===========  =========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   --------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  =========================
     |      Pose             Pose             Pose         matrix product by inverse
     |      Pose             scalar           NxN matrix   element-wise division
     |      ==============   ==============   ===========  =========================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar multiplication is not a group operation so the result will
     |             be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |  animate(self, *args, start=None, **kwargs) -> 'None'
     |      Plot pose object as an animated coordinate frame (superclass method)
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: same as ``self``
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
     |        from the origin in either 2D or 3D.  There are many options, see the
     |        links below.
     |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
     |        frame moving from pose ``X1``, in either 2D or 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=SE3.Ry(0.2))
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
     |
     |  conjugation(self, A: 'NDArray') -> 'NDArray'
     |      Matrix conjugation
     |
     |      :param A: matrix to conjugate
     |      :type A: ndarray
     |      :return: conjugated matrix
     |      :rtype: ndarray
     |
     |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
     |      is the current object.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO2
     |          >>> import numpy as np
     |          >>> R = SO2(0.5)
     |          >>> A = np.array([[10, 0], [0, 1]])
     |          >>> print(R * A * R.inv())
     |          >>> print(R.conjugation(A))
     |
     |  det(self) -> 'Tuple[float, Rn]'
     |      Determinant of rotational component (superclass method)
     |
     |      :return: Determinant of rotational component
     |      :rtype: float or NumPy array
     |
     |      ``x.det()`` is the determinant of the rotation component of the values
     |      of ``x``.
     |
     |      Example::
     |
     |          >>> x=SE3.Rand()
     |          >>> x.det()
     |          1.0000000000000004
     |          >>> x=SE3.Rand(N=2)
     |          >>> x.det()
     |          [0.9999999999999997, 1.0000000000000002]
     |
     |      :SymPy: not supported
     |
     |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
     |      Interpolate between poses (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :param shortest: take the shortest path along the great circle for the rotation
     |      :type shortest: bool, default to True
     |      :return: interpolated pose
     |      :rtype: same as ``self``
     |
     |      - ``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.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
     |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
     |          >>> x.interp(y, 0)    # this is x
     |          >>> x.interp(y, 1)    # this is y
     |          >>> x.interp(y, 0.5)  # this is in between
     |          >>> z = x.interp(y, 11)  # in 11 steps
     |          >>> len(z)
     |          >>> z[0]              # this is x
     |          >>> z[5]              # this is in between
     |
     |      .. note::
     |
     |          - 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
     |
     |  interp1(self, s: 'float' = None) -> 'Self'
     |      Interpolate pose (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1
     |      :type s: array_like
     |      :return: interpolated pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
     |
     |          ======  ======  ===========  ===============================
     |          len(X)  len(s)  len(result)  Result
     |          ======  ======  ===========  ===============================
     |          1       1       1            Y = interp(X, s)
     |          M       1       M            Y[i] = interp(X[i], s)
     |          1       M       M            Y[i] = interp(X, s[i])
     |          ======  ======  ===========  ===============================
     |
     |      Example::
     |
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x.interp(0))
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |          >>> print(x.interp(1))
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
     |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |          >>> y = x.interp(x, np.linspace(0, 1, 10))
     |          >>> len(y)
     |          10
     |          >>> y[5]
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
     |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |
     |      Notes:
     |
     |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
     |
     |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
     |
     |      :SymPy: not supported
     |
     |  ishom(self) -> 'bool'
     |      Test if object belongs to SE(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          True
     |
     |  ishom2(self) -> 'bool'
     |      Test if object belongs to SE(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          True
     |
     |  isrot(self) -> 'bool'
     |      Test if object belongs to SO(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          False
     |
     |  isrot2(self) -> 'bool'
     |      Test if object belongs to SO(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          False
     |
     |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
     |      Logarithm of pose (superclass method)
     |
     |      :return: logarithm
     |      :rtype: ndarray
     |      :raises: ValueError
     |
     |      An efficient closed-form solution of the matrix logarithm.
     |
     |      =====  ======  ===============================
     |      Input         Output
     |      -----  ---------------------------------------
     |      Pose   Shape   Structure
     |      =====  ======  ===============================
     |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
     |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
     |      =====  ======  ===============================
     |
     |      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. ]])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
     |      :func:`~spatialmath.base.transforms3d.trlog`
     |
     |      :SymPy: not supported
     |
     |  norm(self) -> 'Self'
     |      Normalize pose (superclass method)
     |
     |      :return: pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
     |        part of all values has been adjusted to ensure it is a proper orthogonal
     |        matrix rotation.
     |
     |      Example::
     |
     |          >>> x = SE3()
     |          >>> y = x.norm()
     |          >>> y
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |
     |      Notes:
     |
     |      #. Only the direction of A vector (the z-axis) is unchanged.
     |      #. Used to prevent finite word length arithmetic causing transforms to
     |         become 'unnormalized'.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
     |
     |  plot(self, *args, **kwargs) -> 'None'
     |      Plot pose object as a coordinate frame (superclass method)
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
     |        2D or 3D.  There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.plot(frame='A', color='green')
     |
     |      .. plot::
     |
     |          from spatialmath import SE3
     |          X = SE3.Rx(0.3)
     |          X.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
     |
     |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
     |      Print pose as a matrix (superclass method)
     |
     |      :param label: label to print before the matrix, defaults to None
     |      :type label: str, optional
     |      :param file: file to write to, defaults to None
     |      :type file: file object, optional
     |
     |      Print the pose as a matrix, with an optional line beforehand.  By default
     |      the matrix is printed to stdout.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3().print()
     |          >>> SE3().print("pose is:")
     |
     |      :seealso: :meth:`printline` :meth:`strline`
     |
     |  printline(self, *args, **kwargs) -> 'None'
     |      Print pose in compact single line format (superclass method)
     |
     |      :param arg: value for orient option, optional
     |      :type arg: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param file: file to write formatted string to. [default, stdout]
     |      :type file: file object
     |
     |      Print pose in a compact single line format. If ``X`` has multiple
     |      values, print one per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.printline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.printline()
     |          >>> x.printline('angvec')
     |          >>> x.printline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.printline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
     |
     |  prod(self, norm=False, check=True) -> 'Self'
     |      Product of elements (superclass method)
     |
     |      :param norm: normalize the product, defaults to False
     |      :type norm: bool, optional
     |      :param check: check that computed matrix is valid member of group, default True
     |      :bool check: bool, optional
     |      :return: Product of elements
     |      :rtype: pose instance
     |
     |      ``x.prod()`` is the product of the values held by ``x``, ie.
     |      :math:`\prod_i^N T_i`.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
     |          >>> x.prod()
     |
     |      .. note:: When compounding many transformations the product may become
     |          denormalized resulting in a result that is not a proper member of the
     |          group.  You can either disable membership checking by ``check=False``
     |          which is risky, or normalize the result by ``norm=True``.
     |
     |  simplify(self) -> 'Self'
     |      Symbolically simplify matrix values (superclass method)
     |
     |      :return: pose with symbolic elements
     |      :rtype: pose instance
     |
     |      Apply symbolic simplification to every element of every value in the
     |      pose instance.
     |
     |      Example::
     |
     |          >>> a = SE3.Rx(sympy.symbols('theta'))
     |          >>> b = a * a
     |          >>> b
     |          SE3(array([[1, 0, 0, 0.0],
     |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
     |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
     |          [0.0, 0, 0, 1.0]], dtype=object)
     |          >>> b.simplify()
     |          SE3(array([[1, 0, 0, 0],
     |          [0, cos(2*theta), -sin(2*theta), 0],
     |          [0, sin(2*theta), cos(2*theta), 0],
     |          [0, 0, 0, 1.00000000000000]], dtype=object))
     |
     |      .. todo:: No need to simplify the constants in bottom row
     |
     |      :SymPy: supported
     |
     |  stack(self) -> 'NDArray'
     |      Convert to 3-dimensional matrix
     |
     |      :return: 3-dimensional NumPy array
     |      :rtype: ndarray(n,n,m)
     |
     |      Converts the value to a 3-dimensional NumPy array where the values are
     |      stacked along the third axis.  The first two dimensions are given by
     |      ``self.shape``.
     |
     |  strline(self, *args, **kwargs) -> 'str'
     |      Convert pose to compact single line string (superclass method)
     |
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: pose in string format
     |      :rtype: str
     |
     |      Convert pose in a compact single line format. If ``X`` has multiple
     |      values, the string has one pose per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.strline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.strline()
     |          >>> x.strline('angvec')
     |          >>> x.strline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.strline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __new__(cls, *args, **kwargs)
     |      Create the subclass instance (superclass method)
     |
     |      Create a new instance and call the superclass initializer to enable the
     |      ``UserList`` capabilities.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  N
     |      Dimension of the object's group (superclass property)
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
     |      This corresponds to the dimension of the space, 2D or 3D, to which these
     |      rotations or rigid-body motions apply.
     |
     |      Example::
     |
     |          >>> SE3().N
     |          3
     |          >>> SE2().N
     |          2
     |
     |  about
     |      Succinct summary of object type and length (superclass property)
     |
     |      :return: succinct summary
     |      :rtype: str
     |
     |      Displays the type and the number of elements in compact form, for
     |      example::
     |
     |          >>> x = SE3([SE3() for i in range(20)])
     |          >>> len(x)
     |          20
     |          >>> print(x.about)
     |          SE3[20]
     |
     |  isSE
     |      Test if object belongs to SE(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SE2 or SE3
     |      :rtype: bool
     |
     |  isSO
     |      Test if object belongs to SO(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SO2 or SO3
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __len__(self)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\pose2d.py

spatialmath-python.pose3d
Python Library Documentation: module spatialmath.pose3d in spatialmath

NAME
    spatialmath.pose3d - Classes to abstract 3D pose and orientation using matrices in SE(3) and SO(3)

DESCRIPTION
    To use::

        from spatialmath.pose3d import *
        T = SE3.Rx(0.3)

        import spatialmath as sm
        T = sm.SE3.Rx(0.3)


     .. inheritance-diagram:: spatialmath.pose3d
        :top-classes: collections.UserList
        :parts: 1

    .. image:: ../figs/pose-values.png

CLASSES
    spatialmath.baseposematrix.BasePoseMatrix(spatialmath.baseposelist.BasePoseList)
        SO3
            SE3

    class SE3(SO3)
     |  SE3(x=None, y=None, z=None, *, check=True)
     |
     |     SE(3) matrix class
     |
     |     This subclass represents rigid-body motion in 3D space.  Internally it is a
     |     4x4 homogeneous transformation matrix belonging to the group SE(3).
     |
     |  .. inheritance-diagram:: spatialmath.pose3d.SE3
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  Method resolution order:
     |      SE3
     |      SO3
     |      spatialmath.baseposematrix.BasePoseMatrix
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  Ad(self) -> 'R6x6'
     |      Adjoint of SE(3)
     |
     |      :return: adjoint matrix
     |      :rtype: ndarray(6,6)
     |
     |      ``SE3.Ad`` is the 6x6 adjoint matrix
     |
     |      If spatial velocity :math:`\nu = (v_x, v_y, v_z, \omega_x, \omega_y, \omega_z)^T`
     |      and the SE(3) represents the pose of {B} relative to {A},
     |      ie. :math:`{}^A {\bf T}_B`, and the adjoint is :math:`\mathbf{A}` then
     |      :math:`{}^{A}\!\nu = \mathbf{A} {}^{B}\!\nu`.
     |
     |      .. warning:: Do not use this method to map velocities
     |          between robot base and end-effector frames - use ``jacob()``.
     |
     |      .. note:: Use this method to map velocities between two frames on
     |          the same rigid-body.
     |
     |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
     |      :seealso: SE3.jacob, Twist.ad, :func:`~spatialmath.base.tr2jac`
     |      :SymPy: supported
     |
     |  __init__(self, x=None, y=None, z=None, *, check=True)
     |      Construct new SE(3) object
     |
     |      :rtype: SE3 instance
     |
     |      There are multiple call signatures that return an ``SE3`` instance
     |      with one or more values.
     |
     |      - ``SE3()`` null motion, value is the identity matrix.
     |      - ``SE3(x, y, z)`` is a pure translation of (x,y,z)
     |      - ``SE3(T)``  where ``T`` is a 4x4 Numpy  array representing an SE(3)
     |        matrix.  If ``check`` is ``True`` check the matrix belongs to SE(3).
     |      - ``SE3([T1, T2, ... TN])`` has ``N`` values
     |        given by the elements ``Ti`` each of which is a 4x4 NumPy array
     |        representing an SE(3) matrix. If ``check`` is ``True`` check the
     |        matrix belongs to SE(3).
     |      - ``SE3(X)`` where ``X`` is:
     |        -  ``SE3`` is a copy of ``X``
     |        -  ``SO3`` is the rotation of ``X`` with zero translation
     |        -  ``SE2`` is the z-axis rotation and x- and y-axis translation of
     |           ``X``
     |      - ``SE3([X1, X2, ... XN])`` has ``N`` values
     |        given by the elements ``Xi`` each of which is an SE3 instance.
     |
     |      :SymPy: supported
     |
     |  angdist(self, other: 'SE3', metric: 'int' = 6) -> 'float'
     |      Angular distance metric between poses
     |
     |      :param other: second rotation
     |      :type other: SE3 instance
     |      :param metric: metric, default is 6
     |      :type metric: int
     |      :raises TypeError: if other is not an SE3
     |      :return: angle in radians
     |      :rtype: float or ndarray
     |
     |      ``T1.angdist(T2)`` is the geodesic norm, or geodesic distance between the
     |      rotational parts of the two poses.
     |
     |      Several metrics are supported, the first 5 are computed after conversion
     |      to unit quaternions.
     |
     |      ======   ===============================================================
     |      Metric   Details
     |      ======   ===============================================================
     |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
     |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      3        :math:`2 \tan^{-1} \| \q_1 - \q_2\| / \|\q_1 + \q_2\| \in [0, \pi/2]`
     |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
     |      5        :math:`\|I - \mat{R}_1 \mat{R}_2^T\| \in [0, 2]`
     |      6        :math:`\|\log \mat{R}_1 \mat{R}_2^T\| \in [0, \pi]`
     |      ======   ===============================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> T1 = SE3.Rx(0.3)
     |          >>> T2 = SE3.Ry(0.3)
     |          >>> print(T1.angdist(T1))
     |          >>> print(T1.angdist(T2))
     |
     |      .. note::
     |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
     |            numeric errors which push the argument of ``acos()`` marginally
     |            outside its domain [0, 1].
     |          - metrics 2 and 3 are equivalent, but 3 is more robust
     |
     |      :seealso: :func:`UnitQuaternion.angdist`
     |
     |  delta(self, X2: 'Optional[SE3]' = None) -> 'R6'
     |      Infinitesimal difference of SE(3) values
     |
     |      :return: differential motion vector
     |      :rtype: ndarray(6)
     |
     |      ``X1.delta(X2)`` is the differential motion (6x1) corresponding to
     |      infinitesimal motion (in the ``X1`` frame) from pose ``X1`` to ``X2``.
     |
     |      The vector :math:`d = [\delta_x, \delta_y, \delta_z, \theta_x, \theta_y, \theta_z]`
     |      represents infinitesimal translation and rotation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x1 = SE3.Rx(0.3)
     |          >>> x2 = SE3.Rx(0.3001)
     |          >>> x1.delta(x2)
     |
     |      .. note::
     |
     |          - the displacement is only an approximation to the motion, and assumes
     |            that ``X1`` ~ ``X2``.
     |          - can be considered as an approximation to the effect of spatial velocity over a
     |            a time interval, ie. the average spatial velocity multiplied by time.
     |
     |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tr2delta`
     |
     |  inv(self) -> 'SE3'
     |      Inverse of SE(3)
     |
     |      :return: inverse
     |      :rtype: SE3 instance
     |
     |      Efficiently compute the inverse of each of the SE(3) values taking into
     |      account the matrix structure.
     |
     |      .. math::
     |
     |          T = \left[ \begin{array}{cc} \mat{R} & \vec{t} \\ 0 & 1 \end{array} \right],
     |          \mat{T}^{-1} = \left[ \begin{array}{cc} \mat{R}^T & -\mat{R}^T \vec{t} \\ 0 & 1 \end{array} \right]`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3(1,2,3)
     |          >>> x.inv()
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trinv`
     |
     |      :SymPy: supported
     |
     |  jacob(self) -> 'R6x6'
     |      Velocity transform for SE(3)
     |
     |      :return: Jacobian matrix
     |      :rtype: ndarray(6,6)
     |
     |      ``SE3.jacob()`` is the 6x6 Jacobian that maps spatial velocity or
     |      differential motion from frame {B} to frame {A} where the pose of {B}
     |      relative to {A} is represented by the homogeneous transform T =
     |      :math:`{}^A {\bf T}_B`.
     |
     |      .. note::
     |          - To map from frame {A} to frame {B} use the transpose of this matrix.
     |          - Use this method to map velocities between the robot end-effector frame
     |            and the base frames.
     |
     |      .. warning:: Do not use this method to map velocities between two frames
     |          on the same rigid-body.
     |
     |      :seealso: SE3.Ad, Twist.ad, :func:`~spatialmath.base.tr2jac`
     |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
     |      :SymPy: supported
     |
     |  mean(self, tol: 'float' = 20) -> 'SE3'
     |      Mean of a set of SE(3) values
     |
     |      :param tol: iteration tolerance in units of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: the mean SE(3) pose
     |      :rtype: :class:`SE3` instance.
     |
     |      Computes the mean of all the SE(3) values within the :class:`SE3` instance.  Rotations are
     |      averaged using the Karcher mean, and translations are averaged using the
     |      arithmetic mean.
     |
     |      :references:
     |          - `**Hartley, Trumpf** - "Rotation Averaging" - IJCV 2011 <https://users.cecs.anu.edu.au/~hartley/Papers/PDF/Hartley-Trumpf:Rotation-averaging:IJCV.pdf>`_, Algorithm 1, page 15.
     |          - `Karcher mean <https://en.wikipedia.org/wiki/Karcher_mean>`_
     |
     |      :seealso:  :meth:`SO3.mean`
     |
     |  rtvec(self) -> 'Tuple[R3, R3]'
     |      Convert to OpenCV-style rotation and translation vectors
     |
     |      :return: rotation and translation vectors
     |      :rtype: ndarray(3), ndarray(3)
     |
     |      Many OpenCV functions accept pose as two 3-vectors: a rotation vector using
     |      exponential coordinates and a translation vector.  This method combines them
     |      into an SE(3) instance.
     |
     |      :seealso: :meth:`rtvec`
     |
     |  twist(self) -> 'Twist3'
     |      SE(3) as twist
     |
     |      :return: equivalent rigid-body motion as a twist vector
     |      :rtype: Twist3 instance
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3(1,2,3)
     |          >>> x.twist()
     |
     |      :seealso: :func:`spatialmath.twist.Twist3`
     |
     |  yaw_SE2(self, order: 'str' = 'zyx') -> 'SE2'
     |      Create SE(2) from SE(3) yaw angle.
     |
     |      :param order: angle sequence order, default to 'zyx'
     |      :type order: str
     |      :return: SE(2) with same rotation as the yaw angle using the roll-pitch-yaw convention,
     |          and translation along the roll-pitch axes.
     |      :rtype: SE2 instance
     |
     |      Roll-pitch-yaw corresponds to successive rotations about the axes specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
     |            to the optic axis and x-axis parallel to the pixel rows.
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  AngVec(theta: 'float', v: 'ArrayLike3', *, unit: 'str' = 'rad') -> 'SE3'
     |      Create an SE(3) pure rotation matrix from rotation angle and axis
     |
     |      :param θ: rotation
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param v: rotation axis
     |      :type v: array_like(3)
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      ``SE3.AngVec(θ, v)`` is an SE(3) rotation defined by
     |      a rotation of ``θ`` about the vector ``v``.
     |
     |      .. deprecated:: 0.9.8
     |          Use :meth:`AngleAxis` instead.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.pose3d.SE3.EulerVec`, :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  AngleAxis(theta: 'float', v: 'ArrayLike3', *, unit: 'Optional[unit]' = 'rad') -> 'SE3'
     |      Create an SE(3) pure rotation matrix from rotation angle and axis
     |
     |      :param θ: rotation
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param v: rotation axis
     |      :type v: array_like(3)
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      ``SE3.AngleAxis(θ, v)`` is an SE(3) rotation defined by
     |      a rotation of ``θ`` about the vector ``v``.
     |
     |      .. math::
     |
     |          \mbox{if}\,\, \theta \left\{ \begin{array}{ll}
     |              = 0 & \mbox{return identity matrix}\\
     |              \ne 0 & \mbox{v must have a finite length}
     |              \end{array}
     |              \right.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.pose3d.SE3.EulerVec`, :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  CopyFrom(T: 'SE3Array', check: 'bool' = True) -> 'SE3'
     |      Create an SE(3) from a 4x4 numpy array that is passed by value.
     |
     |      :param T: homogeneous transformation
     |      :type T: ndarray(4, 4)
     |      :param check: check rotation validity, defaults to True
     |      :type check: bool, optional
     |      :raises ValueError: bad rotation matrix, bad transformation matrix
     |      :return: SE(3) matrix representing that transformation
     |      :rtype: SE3 instance
     |
     |  Delta(d: 'ArrayLike6') -> 'SE3'
     |      Create SE(3) from differential motion
     |
     |      :param d: differential motion
     |      :type d: array_like(6)
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      ``SE3.Delta2tr(d)`` is an SE(3) representing differential
     |      motion :math:`d = [\delta_x, \delta_y, \delta_z, \theta_x, \theta_y, \theta_z]`.
     |
     |      :Reference: Robotics, Vision & Control for Python, Section 3.1, P. Corke, Springer 2023.
     |
     |      :seealso: :meth:`~delta` :func:`~spatialmath.base.transform3d.delta2tr`
     |      :SymPy: supported
     |
     |  Eul(*angles, unit='rad') -> 'SE3'
     |      Create an SE(3) pure rotation from Euler angles
     |
     |      :param 𝚪: Euler angles
     |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Eul(𝚪)`` is an SE(3) rotation defined by a 3-vector of Euler
     |        angles :math:`\Gamma=(\phi, \theta, \psi)` which correspond to
     |        consecutive rotations about the Z, Y, Z axes respectively.
     |
     |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of
     |      rotations each defined by Euler angles corresponding to the rows of
     |      ``𝚪``.
     |
     |      - ``SE3.Eul(φ, θ, ψ)`` as above but the angles are provided as three
     |        scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Eul(0.1, 0.2, 0.3)
     |          >>> SE3.Eul([0.1, 0.2, 0.3])
     |          >>> SE3.Eul(10, 20, 30, unit="deg")
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.eul`, :func:`~spatialmath.base.transforms3d.eul2r`
     |      :SymPy: supported
     |
     |  EulerVec(w: 'ArrayLike3') -> 'SE3'
     |      Construct a new SE(3) pure rotation matrix from an Euler rotation vector
     |
     |      :param ω: rotation axis
     |      :type ω: array_like(3)
     |      :return: SE(3) rotation
     |      :rtype: SE3 instance
     |
     |      ``SE3.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
     |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
     |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.EulerVec([0.5,0,0])
     |
     |      .. note:: :math:`\theta = 0` the result in an identity matrix, otherwise
     |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.AngVec`, :func:`~spatialmath.base.transforms3d.angvec2tr`
     |
     |  Exp(S: 'Union[R6, R4x4]', check: 'bool' = True) -> 'SE3'
     |      Create an SE(3) matrix from se(3)
     |
     |      :param S: Lie algebra se(3) matrix
     |      :type S: ndarray(6), ndarray(4,4)
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Exp(S)`` is an SE(3) rotation defined by its Lie algebra
     |        which is a 4x4 se(3) matrix (skew symmetric)
     |      - ``SE3.Exp(t)`` is an SE(3) rotation defined by a 6-element twist
     |        vector (the unique elements of the se(3) skew-symmetric matrix)
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trexp`, :func:`~spatialmath.base.transformsNd.skew`
     |
     |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'SE3'
     |      Create an SE(3) pure rotation from two vectors
     |
     |      :param o: 3-vector parallel to Y- axis
     |      :type o: array_like(3)
     |      :param a: 3-vector parallel to the Z-axis
     |      :type a: array_like(3)
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      ``SE3.OA(o, a)`` is an SE(3) rotation defined in terms of vectors ``o``
     |      and ``a`` respectively parallel to the Y- and Z-axes of its reference
     |      frame.  In robotics these axes are respectively called the *orientation*
     |      and *approach* vectors defined such that :math:`\mathbf{R} = [n, o, a]`
     |      and :math:`n = o \times a`.
     |
     |      .. note::
     |
     |          - The ``a`` vector is the only guaranteed to have the same direction in the resulting
     |            rotation matrix
     |          - ``o`` and ``a`` do not have to be unit-length, they are normalized
     |          - ``o`` and ``a`` do not have to be orthogonal, so long as they are not parallel
     |            ``o`` is adjusted to be orthogonal to ``a``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.OA([1, 0, 0], [0, 0, -1])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.oa2r`
     |
     |  RPY(*angles, unit='rad', order='zyx') -> 'SE3'
     |      Create an SE(3) pure rotation from roll-pitch-yaw angles
     |
     |      :param 𝚪: roll-pitch-yaw angles
     |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
     |      :type order: str
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.RPY(𝚪)`` is an SE(3) rotation defined by a 3-vector of roll,
     |        pitch, yaw angles :math:`\Gamma=(r, p, y)` which correspond to
     |        successive rotations about the axes specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  This is the **convention** for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. This is the **convention** for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. This is the **convention** for a camera with z-axis parallel
     |            to the optical axis and x-axis parallel to the pixel rows.
     |
     |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of rotations each defined by RPY angles
     |      corresponding to the rows of ``𝚪``.
     |
     |      - ``SE3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
     |        scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.RPY(0.1, 0.2, 0.3)
     |          >>> SE3.RPY([0.1, 0.2, 0.3])
     |          >>> SE3.RPY(0.1, 0.2, 0.3, order='xyz')
     |          >>> SE3.RPY(10, 20, 30, unit='deg')
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.rpy`, :func:`~spatialmath.base.transforms3d.rpy2r`
     |      :SymPy: supported
     |
     |  RTvec(rvec: 'ArrayLike3', tvec: 'ArrayLike3') -> 'Self'
     |      Construct a new SE(3) from OpenCV-style rotation and translation vectors
     |
     |      :param rvec: rotation as exponential coordinates
     |      :type rvec: ArrayLike3
     |      :param tvec: translation vector
     |      :type tvec: ArrayLike3
     |      :return: An SE(3) instance
     |      :rtype: SE3 instance
     |
     |      Many OpenCV functions (such as pose estimation) return pose as two 3-vectors: a
     |      rotation vector using exponential coordinates and a translation vector.  This
     |      method combines them into an SE(3) instance.
     |
     |      :seealso: :meth:`rtvec`
     |
     |  Rand(N: 'int' = 1, xrange: 'Optional[ArrayLike2]' = (-1, 1), yrange: 'Optional[ArrayLike2]' = (-1, 1), zrange: 'Optional[ArrayLike2]' = (-1, 1), theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'SE3'
     |      Create a random SE(3)
     |
     |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
     |      :type xrange: 2-element sequence, optional
     |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
     |      :type yrange: 2-element sequence, optional
     |      :param zrange: z-axis range [min,max], defaults to [-1, 1]
     |      :type zrange: 2-element sequence, optional
     |      :param theta_range: angular magnitude range [min,max], defaults to None -> [0,pi].
     |      :type xrange: 2-element sequence, optional
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param N: number of random transforms
     |      :type N: int
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      Return an SE3 instance with random rotation and translation.
     |
     |      - ``SE3.Rand()`` is a random SE(3) translation.
     |      - ``SE3.Rand(N)`` is an SE3 object containing a sequence of N random
     |        poses.
     |
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rand(2)
     |
     |      :seealso: :func:`~spatialmath.quaternions.UnitQuaternion.Rand`
     |
     |  Rt(R: 'Union[SO3, SO3Array]', t: 'Optional[ArrayLike3]' = None, check: 'bool' = True) -> 'SE3'
     |      Create an SE(3) from rotation and translation
     |
     |      :param R: rotation
     |      :type R: SO3 or ndarray(3,3)
     |      :param t: translation
     |      :type t: array_like(3)
     |      :param check: check rotation validity, defaults to True
     |      :type check: bool, optional
     |      :raises ValueError: bad rotation matrix
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |  Rx(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
     |      Create anSE(3) pure rotation about the X-axis
     |
     |      :param θ: rotation angle about X-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param t: translation, optional
     |      :type t: 3-element array-like
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Rx(θ)`` is an SE(3) rotation of θ radians about the x-axis
     |      - ``SE3.Rx(θ, "deg")`` as above but θ is in degrees
     |      - ``SE3.Rx(θ, t=T)`` as above but also sets the translational component
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      .. note:: The translation option only works for the scalar θ case.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.3)
     |          >>> SE3.Rx([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trotx`
     |      :SymPy: supported
     |
     |  Ry(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
     |      Create an SE(3) pure rotation about the Y-axis
     |
     |      :param θ: rotation angle about X-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param t: translation, optional
     |      :type t: 3-element array-like
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Ry(θ)`` is an SO(3) rotation of θ radians about the y-axis
     |      - ``SE3.Ry(θ, "deg")`` as above but θ is in degrees
     |      - ``SE3.Ry(θ, t=T)`` as above but also sets the translational component
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      .. note:: The translation option only works for the scalar θ case.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Ry(0.3)
     |          >>> SE3.Ry([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.troty`
     |      :SymPy: supported
     |
     |  Rz(theta: 'ArrayLike', unit: 'str' = 'rad', t: 'Optional[ArrayLike3]' = None) -> 'SE3'
     |      Create an SE(3) pure rotation about the Z-axis
     |
     |      :param θ: rotation angle about Z-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param t: translation, optional
     |      :type t: 3-element array-like
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Rz(θ)`` is an SO(3) rotation of θ radians about the z-axis
     |      - ``SE3.Rz(θ, "deg")`` as above but θ is in degrees
     |      - ``SE3.Rz(θ, t=T)`` as above but also sets the translational component
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      .. note:: The translation option only works for the scalar θ case.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rz(0.3)
     |          >>> SE3.Rz([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trotz`
     |      :SymPy: supported
     |
     |  Trans(x, y=None, z=None) -> 'SE3'
     |      Create SE(3) from translation vector
     |
     |      :param x: x-coordinate or translation vector
     |      :type x: float or array_like(3)
     |      :param y: y-coordinate, defaults to None
     |      :type y: float, optional
     |      :param z: z-coordinate, defaults to None
     |      :type z: float, optional
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``SE3.Trans(x, y, z)`` is an SE(3) representing pure translation.
     |
     |      - ``SE3.Trans([x, y, z])`` as above, but translation is given as an
     |        array.
     |
     |      - ``SE3.Trans(t)`` where ``t`` is Nx3 then create an SE3 object with
     |        N elements whose translation is defined by the rows of ``t``.
     |
     |  Tx(x: 'float') -> 'SE3'
     |      Create an SE(3) translation along the X-axis
     |
     |      :param x: translation distance along the X-axis
     |      :type x: float
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      `SE3.Tx(x)` is an SE(3) translation of ``x`` along the x-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Tx(2)
     |          >>> SE3.Tx([2,3])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Ty(y: 'float') -> 'SE3'
     |      Create an SE(3) translation along the Y-axis
     |
     |      :param y: translation distance along the Y-axis
     |      :type y: float
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      `SE3.Ty(y) is an SE(3) translation of ``y`` along the y-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Ty(2)
     |          >>> SE3.Ty([2,3])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Tz(z: 'float') -> 'SE3'
     |      Create an SE(3) translation along the Z-axis
     |
     |      :param z: translation distance along the Z-axis
     |      :type z: float
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      `SE3.Tz(z)` is an SE(3) translation of ``z`` along the z-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Tz(2)
     |          >>> SE3.Tz([2,3])
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.transl`
     |      :SymPy: supported
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x: 'NDArray', check: 'bool' = True) -> 'bool'
     |      Test if matrix is a valid SE(3)
     |
     |      :param x: matrix to test
     |      :type x: numpy.ndarray
     |      :return: ``True`` if the matrix is 4x4 and a valid element of SE(3), ie. it
     |               is a valid homogeneous transformation matrix.
     |      :rtype: bool
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.ishom`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  shape
     |      Shape of the object's internal matrix representation
     |
     |      :return: (4,4)
     |      :rtype: tuple
     |
     |      Each value within the ``SE3`` instance is a NumPy array of this shape.
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  R
     |      SO(3) or SE(3) as rotation matrix
     |
     |      :return: rotational component
     |      :rtype: ndarray(3,3)
     |
     |      ``x.R`` is the rotation matrix component of ``x`` as an array with
     |      shape (3,3). If ``len(x) > 1``, return an array with shape=(N,3,3).
     |
     |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
     |          ``x[i]``. This is different to the MATLAB version where the i'th
     |          rotation matrix is ``x(:,:,i)``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> x = SO3.Rx(0.3)
     |          >>> x.R
     |
     |      :SymPy: supported
     |
     |  t
     |      Translational component of SE(3)
     |
     |      :return: translational component of SE(3)
     |      :rtype: numpy.ndarray
     |
     |      ``x.t`` is the translational component of ``x`` as an array with
     |      shape (3,). If ``len(x) > 1``, return an array with shape=(N,3).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3(1,2,3)
     |          >>> x.t
     |          >>> x = SE3([ SE3(1,2,3), SE3(4,5,6)])
     |          >>> x.t
     |
     |      :SymPy: supported
     |
     |  x
     |      First element of translational component of SE(3)
     |
     |      :return: first element of translational component of SE(3)
     |      :rtype: float
     |
     |      If ``len(v) > 1``, return an array with shape=(N,).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> v = SE3(1,2,3)
     |          >>> v.x
     |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
     |          >>> v.x
     |
     |      :SymPy: supported
     |
     |  y
     |      Second element of translational component of SE(3)
     |
     |      :return: second element of translational component of SE(3)
     |      :rtype: float
     |
     |      If ``len(v) > 1``, return an array with shape=(N,).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> v = SE3(1,2,3)
     |          >>> v.y
     |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
     |          >>> v.y
     |
     |      :SymPy: supported
     |
     |  z
     |      Third element of translational component of SE(3)
     |
     |      :return: third element of translational component of SE(3)
     |      :rtype: float
     |
     |      If ``len(v) > 1``, return an array with shape=(N,).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> v = SE3(1,2,3)
     |          >>> v.z
     |          >>> v = SE3([ SE3(1,2,3), SE3(4,5,6)])
     |          >>> v.z
     |
     |      :SymPy: supported
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SO3:
     |
     |  UnitQuaternion(self) -> 'UnitQuaternion'
     |      SO3 as a unit quaternion instance
     |
     |      :return: a unit quaternion representation
     |      :rtype: UnitQuaternion instance
     |
     |      ``R.UnitQuaternion()`` is an ``UnitQuaternion`` instance representing the same rotation
     |      as the SO3 rotation ``R``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> SO3.Rz(0.3).UnitQuaternion()
     |
     |  angvec(self, unit: 'str' = 'rad') -> 'Tuple[float, R3]'
     |      SO(3) or SE(3) as angle and rotation vector
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: :math:`(\theta, \hat{\bf v})`
     |      :rtype: float or ndarray(3)
     |
     |      ``x.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
     |      angle and a rotation axis.
     |
     |      By default the angle is in radians but can be changed setting `unit='deg'`.
     |
     |      .. note::
     |
     |          - If the input is SE(3) the translation component is ignored.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> R = SO3.Rx(0.3)
     |          >>> R.angvec()
     |
     |      :seealso: :meth:`eulervec` :meth:`AngVec` :meth:`~spatialmath.quaternion.UnitQuaternion.angvec` :meth:`~spatialmath.quaternion.AngVec`, :func:`~angvec2r`
     |
     |  eul(self, unit: 'str' = 'rad', flip: 'bool' = False) -> 'Union[R3, RNx3]'
     |      SO(3) or SE(3) as Euler angles
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of Euler angles
     |      :rtype: ndarray(3,), ndarray(n,3)
     |
     |      ``x.eul`` is the Euler angle representation of the rotation.  Euler angles are
     |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
     |      rotations about the Z, Y, Z axes respectively.
     |
     |      If ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(3,N)
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.tr2eul`
     |      :SymPy: not supported
     |
     |  eulervec(self) -> 'R3'
     |      SO(3) or SE(3) as Euler vector (exponential coordinates)
     |
     |      :return: :math:`\theta \hat{\bf v}`
     |      :rtype: ndarray(3)
     |
     |      ``x.eulervec()`` is the Euler vector (or exponential coordinates) which
     |      is related to angle-axis notation and is the product of the rotation
     |      angle and the rotation axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> R = SO3.Rx(0.3)
     |          >>> R.eulervec()
     |
     |      .. note::
     |
     |          - If the input is SE(3) the translation component is ignored.
     |
     |      :seealso: :meth:`angvec` :func:`~angvec2r`
     |
     |  rpy(self, unit: 'str' = 'rad', order: 'str' = 'zyx') -> 'Union[R3, RNx3]'
     |      SO(3) or SE(3) as roll-pitch-yaw angles
     |
     |      :param order: angle sequence order, default to 'zyx'
     |      :type order: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of roll-pitch-yaw angles
     |      :rtype: ndarray(3,), ndarray(n,3)
     |
     |      ``x.rpy`` is the roll-pitch-yaw angle representation of the rotation.  The angles are
     |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
     |      specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
     |            to the optic axis and x-axis parallel to the pixel rows.
     |
     |      If `len(x)` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(3,N)
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.RPY`, :func:`~spatialmath.base.transforms3d.tr2rpy`
     |      :SymPy: not supported
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from SO3:
     |
     |  RotatedVector(v1: 'ArrayLike3', v2: 'ArrayLike3', tol=20) -> 'Self'
     |      Construct a new SO(3) from a vector and its rotated image
     |
     |      :param v1: initial vector
     |      :type v1: array_like(3)
     |      :param v2: vector after rotation
     |      :type v2: array_like(3)
     |      :param tol: tolerance for singularity in units of eps, defaults to 20
     |      :type tol: float
     |      :return: SO(3) rotation
     |      :rtype: :class:`SO3` instance
     |
     |      ``SO3.RotatedVector(v1, v2)`` is an SO(3) rotation defined in terms of
     |      two vectors. The rotation takes vector ``v1`` to ``v2``.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> v1 = [1, 2, 3]
     |          >>> v2 = SO3.Eul(0.3, 0.4, 0.5) * v1
     |          >>> print(v2)
     |          >>> R = SO3.RotatedVector(v1, v2)
     |          >>> print(R)
     |          >>> print(R * v1)
     |
     |      .. note:: The vectors do not have to be unit-length.
     |
     |  TwoVectors(x: 'Optional[Union[str, ArrayLike3]]' = None, y: 'Optional[Union[str, ArrayLike3]]' = None, z: 'Optional[Union[str, ArrayLike3]]' = None) -> 'Self'
     |      Construct a new SO(3) from any two vectors
     |
     |      :param x: new x-axis, defaults to None
     |      :type x: str, array_like(3), optional
     |      :param y: new y-axis, defaults to None
     |      :type y: str, array_like(3), optional
     |      :param z: new z-axis, defaults to None
     |      :type z: str, array_like(3), optional
     |
     |      Create a rotation by defining the direction of two of the new
     |      axes in terms of the old axes.  Axes are denoted by strings ``"x"``,
     |      ``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
     |
     |      The directions can also be specified by 3-element vectors. If the vectors are not orthogonal,
     |      they will orthogonalized w.r.t. the first available dimension. I.e. if x is available, it will be
     |      normalized and the remaining vector will be orthogonalized w.r.t. x, else, y will be normalized
     |      and z will be orthogonalized w.r.t. y.
     |
     |      To create a rotation where the new frame has its x-axis in -z-direction
     |      of the previous frame, and its z-axis in the x-direction of the previous
     |      frame is::
     |
     |          >>> SO3.TwoVectors(x='-z', z='x')
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SO3:
     |
     |  a
     |      Approach vector of SO(3) or SE(3)
     |
     |      :return: approach vector
     |      :rtype: ndarray(3)
     |
     |      This is the third column of the rotation submatrix, sometimes called the
     |      *approach vector*.  It is parallel to the z-axis of the frame defined by
     |      this pose.
     |
     |  n
     |      Normal vector of SO(3) or SE(3)
     |
     |      :return: normal vector
     |      :rtype: ndarray(3)
     |
     |      This is the first column of the rotation submatrix, sometimes called the
     |      *normal vector*.  It is parallel to the x-axis of the frame defined by
     |      this pose.
     |
     |  o
     |      Orientation vector of SO(3) or SE(3)
     |
     |      :return: orientation vector
     |      :rtype: ndarray(3)
     |
     |      This is the second column of the rotation submatrix, sometimes called
     |      the *orientation vector*.  It is parallel to the y-axis of the frame
     |      defined by this pose.
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __add__(left, right)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Add the elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
     |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
     |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ========================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ========================
     |      Pose             Pose             NxN matrix   element-wise matrix sum
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ========================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar + Pose is handled by :meth:`__radd__`
     |          #. Addition is commutative
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose addition either or both operands may hold more than one value which
     |      results in the sum holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``sum = left + right``
     |       1          M             M    ``sum[i] = left + right[i]``
     |       N          1             M    ``sum[i] = left[i] + right``
     |       M          M             M    ``sum[i] = left[i] + right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __eq__(left, right: 'Self') -> 'bool'
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for equality
     |
     |      ``X == Y`` is true of the poses are of the same type and numerically
     |      equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the equality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``eq = left == right``
     |       1          M             M    ``eq[i] = left == right[i]``
     |       N          1             M    ``eq[i] = left[i] == right``
     |       M          M             M    ``eq[i] = left[i] == right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __iadd__(left, right)
     |      Overloaded ``+=`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
     |      - ``X += s`` elementwise addition of the matrix elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__add__``
     |
     |  __imul__(left, right)
     |      Overloaded ``*=`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
     |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__mul__``
     |
     |  __isub__(left, right: 'Self')
     |      Overloaded ``-=`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises: ValueError
     |
     |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
     |        and ``Y`` and places the result in ``X``
     |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
     |        and the scalar ``s`` and places the result in ``X``
     |
     |      :seealso: ``__sub__``
     |
     |  __itruediv__(left, right)
     |      Overloaded ``/=`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
     |      - ``X /= s`` performs elementwise division of the elements of ``X``
     |        by ``s`` and places the result in ``X``
     |
     |      :seealso: ``__truediv__``
     |
     |  __matmul__(left, right)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :return: Product of two operands with normalization
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
     |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
     |        and places the result in ``X``
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally
     |          update over many cycles.
     |
     |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Pose composition, scaling or vector transformation:
     |
     |      - ``X * Y`` compounds the poses ``X`` and ``Y``
     |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
     |
     |      ==============   ==============   ===========  ======================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ======================
     |      Pose             Pose             Pose         matrix product
     |      Pose             scalar           NxN matrix   element-wise product
     |      scalar           Pose             NxN matrix   element-wise product
     |      Pose             N-vector         N-vector     vector transform
     |      Pose             NxM matrix       NxM matrix   transform each column
     |      ==============   ==============   ===========  ======================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar x Pose is handled by __rmul__`
     |          #. Scalar multiplication is commutative but the result is not a group
     |             operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
     |          SE3(array([[0., 0., 1., 0.],
     |                  [1., 0., 0., 0.],
     |                  [0., 1., 0., 0.],
     |                  [0., 0., 0., 1.]]))
     |          >>> SE3.Rx(pi/2) * 2
     |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
     |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
     |
     |      For vector transformation there are three cases:
     |
     |      =========  ===========  =====  ==========================
     |            Multiplicands             Product
     |      ----------------------  ---------------------------------
     |      len(left)  right.shape  shape  operation
     |      =========  ===========  =====  ==========================
     |      1          (N,)         (N,)   vector transformation
     |      M          (N,)         (N,M)  vector transformations
     |      1          (N,M)        (N,M)  column transformation
     |      =========  ===========  =====  ==========================
     |
     |      .. note::
     |          - The vector is an array-like, a 1D NumPy array or a list/tuple
     |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
     |            form, transformed, then converted back to Euclidean form.
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * [0, 1, 0]
     |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
     |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
     |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :return: Inequality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for inequality
     |
     |      - ``X != Y`` is true of the poses are of the same type but not numerically
     |        equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the inequality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``ne = left != right``
     |       1          M             M    ``ne[i] = left != right[i]``
     |       N          1             M    ``ne[i] = left[i] != right``
     |       M          M             M    ``ne[i] = left[i] != right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __pow__(self, n: 'int') -> 'Self'
     |      Overloaded ``**`` operator (superclass method)
     |
     |      :param n: exponent
     |      :type n: int
     |      :return: pose to the power ``n``
     |      :rtype: pose instance
     |
     |      ``X**n`` raise all values held in `X` to the specified power using repeated
     |      multiplication.  If ``n`` < 0 then the result is inverted.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.1) ** 2
     |          >>> SE3.Rx([0, 0.1]) ** 2
     |
     |  __radd__(right, left)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__add__`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> repr(x)
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Left-multiplication
     |
     |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
     |        elements of ``X`` by ``s`` and the result is a NumPy array.
     |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
     |        of ``A`` and ``X`` and the result is a NumPy array.
     |
     |      :seealso: :func:`__mul__`
     |
     |  __rsub__(right, left: 'Self')
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__sub__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of pose (superclass method)
     |
     |      :return: readable representation of the pose
     |      :rtype: str
     |
     |      Convert the pose's matrix value to a simple grid of numbers.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x)
     |
     |      Notes:
     |
     |          - By default, the output is colorised for an ANSI terminal console:
     |
     |              * red: rotational elements
     |              * blue: translational elements
     |              * white: constant elements
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Subtract elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
     |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
     |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ==============================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ==============================
     |      Pose             Pose             NxN matrix   element-wise matrix difference
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ==============================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar - Pose is handled by :meth:`__rsub__`
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose subtraction either or both operands may hold more than one value which
     |      results in the difference holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``diff = left - right``
     |       1          M             M    ``diff[i] = left - right[i]``
     |       N          1             M    ``diff[i] = left[i] - right``
     |       M          M             M    ``diff[i] = left[i]  right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __truediv__(left, right)
     |      Overloaded ``/`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      Pose composition or scaling:
     |
     |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
     |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
     |
     |      ==============   ==============   ===========  =========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   --------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  =========================
     |      Pose             Pose             Pose         matrix product by inverse
     |      Pose             scalar           NxN matrix   element-wise division
     |      ==============   ==============   ===========  =========================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar multiplication is not a group operation so the result will
     |             be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |  animate(self, *args, start=None, **kwargs) -> 'None'
     |      Plot pose object as an animated coordinate frame (superclass method)
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: same as ``self``
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
     |        from the origin in either 2D or 3D.  There are many options, see the
     |        links below.
     |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
     |        frame moving from pose ``X1``, in either 2D or 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=SE3.Ry(0.2))
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
     |
     |  conjugation(self, A: 'NDArray') -> 'NDArray'
     |      Matrix conjugation
     |
     |      :param A: matrix to conjugate
     |      :type A: ndarray
     |      :return: conjugated matrix
     |      :rtype: ndarray
     |
     |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
     |      is the current object.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO2
     |          >>> import numpy as np
     |          >>> R = SO2(0.5)
     |          >>> A = np.array([[10, 0], [0, 1]])
     |          >>> print(R * A * R.inv())
     |          >>> print(R.conjugation(A))
     |
     |  det(self) -> 'Tuple[float, Rn]'
     |      Determinant of rotational component (superclass method)
     |
     |      :return: Determinant of rotational component
     |      :rtype: float or NumPy array
     |
     |      ``x.det()`` is the determinant of the rotation component of the values
     |      of ``x``.
     |
     |      Example::
     |
     |          >>> x=SE3.Rand()
     |          >>> x.det()
     |          1.0000000000000004
     |          >>> x=SE3.Rand(N=2)
     |          >>> x.det()
     |          [0.9999999999999997, 1.0000000000000002]
     |
     |      :SymPy: not supported
     |
     |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
     |      Interpolate between poses (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :param shortest: take the shortest path along the great circle for the rotation
     |      :type shortest: bool, default to True
     |      :return: interpolated pose
     |      :rtype: same as ``self``
     |
     |      - ``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.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
     |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
     |          >>> x.interp(y, 0)    # this is x
     |          >>> x.interp(y, 1)    # this is y
     |          >>> x.interp(y, 0.5)  # this is in between
     |          >>> z = x.interp(y, 11)  # in 11 steps
     |          >>> len(z)
     |          >>> z[0]              # this is x
     |          >>> z[5]              # this is in between
     |
     |      .. note::
     |
     |          - 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
     |
     |  interp1(self, s: 'float' = None) -> 'Self'
     |      Interpolate pose (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1
     |      :type s: array_like
     |      :return: interpolated pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
     |
     |          ======  ======  ===========  ===============================
     |          len(X)  len(s)  len(result)  Result
     |          ======  ======  ===========  ===============================
     |          1       1       1            Y = interp(X, s)
     |          M       1       M            Y[i] = interp(X[i], s)
     |          1       M       M            Y[i] = interp(X, s[i])
     |          ======  ======  ===========  ===============================
     |
     |      Example::
     |
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x.interp(0))
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |          >>> print(x.interp(1))
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
     |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |          >>> y = x.interp(x, np.linspace(0, 1, 10))
     |          >>> len(y)
     |          10
     |          >>> y[5]
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
     |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |
     |      Notes:
     |
     |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
     |
     |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
     |
     |      :SymPy: not supported
     |
     |  ishom(self) -> 'bool'
     |      Test if object belongs to SE(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          True
     |
     |  ishom2(self) -> 'bool'
     |      Test if object belongs to SE(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          True
     |
     |  isrot(self) -> 'bool'
     |      Test if object belongs to SO(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          False
     |
     |  isrot2(self) -> 'bool'
     |      Test if object belongs to SO(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          False
     |
     |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
     |      Logarithm of pose (superclass method)
     |
     |      :return: logarithm
     |      :rtype: ndarray
     |      :raises: ValueError
     |
     |      An efficient closed-form solution of the matrix logarithm.
     |
     |      =====  ======  ===============================
     |      Input         Output
     |      -----  ---------------------------------------
     |      Pose   Shape   Structure
     |      =====  ======  ===============================
     |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
     |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
     |      =====  ======  ===============================
     |
     |      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. ]])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
     |      :func:`~spatialmath.base.transforms3d.trlog`
     |
     |      :SymPy: not supported
     |
     |  norm(self) -> 'Self'
     |      Normalize pose (superclass method)
     |
     |      :return: pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
     |        part of all values has been adjusted to ensure it is a proper orthogonal
     |        matrix rotation.
     |
     |      Example::
     |
     |          >>> x = SE3()
     |          >>> y = x.norm()
     |          >>> y
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |
     |      Notes:
     |
     |      #. Only the direction of A vector (the z-axis) is unchanged.
     |      #. Used to prevent finite word length arithmetic causing transforms to
     |         become 'unnormalized'.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
     |
     |  plot(self, *args, **kwargs) -> 'None'
     |      Plot pose object as a coordinate frame (superclass method)
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
     |        2D or 3D.  There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.plot(frame='A', color='green')
     |
     |      .. plot::
     |
     |          from spatialmath import SE3
     |          X = SE3.Rx(0.3)
     |          X.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
     |
     |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
     |      Print pose as a matrix (superclass method)
     |
     |      :param label: label to print before the matrix, defaults to None
     |      :type label: str, optional
     |      :param file: file to write to, defaults to None
     |      :type file: file object, optional
     |
     |      Print the pose as a matrix, with an optional line beforehand.  By default
     |      the matrix is printed to stdout.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3().print()
     |          >>> SE3().print("pose is:")
     |
     |      :seealso: :meth:`printline` :meth:`strline`
     |
     |  printline(self, *args, **kwargs) -> 'None'
     |      Print pose in compact single line format (superclass method)
     |
     |      :param arg: value for orient option, optional
     |      :type arg: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param file: file to write formatted string to. [default, stdout]
     |      :type file: file object
     |
     |      Print pose in a compact single line format. If ``X`` has multiple
     |      values, print one per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.printline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.printline()
     |          >>> x.printline('angvec')
     |          >>> x.printline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.printline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
     |
     |  prod(self, norm=False, check=True) -> 'Self'
     |      Product of elements (superclass method)
     |
     |      :param norm: normalize the product, defaults to False
     |      :type norm: bool, optional
     |      :param check: check that computed matrix is valid member of group, default True
     |      :bool check: bool, optional
     |      :return: Product of elements
     |      :rtype: pose instance
     |
     |      ``x.prod()`` is the product of the values held by ``x``, ie.
     |      :math:`\prod_i^N T_i`.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
     |          >>> x.prod()
     |
     |      .. note:: When compounding many transformations the product may become
     |          denormalized resulting in a result that is not a proper member of the
     |          group.  You can either disable membership checking by ``check=False``
     |          which is risky, or normalize the result by ``norm=True``.
     |
     |  simplify(self) -> 'Self'
     |      Symbolically simplify matrix values (superclass method)
     |
     |      :return: pose with symbolic elements
     |      :rtype: pose instance
     |
     |      Apply symbolic simplification to every element of every value in the
     |      pose instance.
     |
     |      Example::
     |
     |          >>> a = SE3.Rx(sympy.symbols('theta'))
     |          >>> b = a * a
     |          >>> b
     |          SE3(array([[1, 0, 0, 0.0],
     |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
     |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
     |          [0.0, 0, 0, 1.0]], dtype=object)
     |          >>> b.simplify()
     |          SE3(array([[1, 0, 0, 0],
     |          [0, cos(2*theta), -sin(2*theta), 0],
     |          [0, sin(2*theta), cos(2*theta), 0],
     |          [0, 0, 0, 1.00000000000000]], dtype=object))
     |
     |      .. todo:: No need to simplify the constants in bottom row
     |
     |      :SymPy: supported
     |
     |  stack(self) -> 'NDArray'
     |      Convert to 3-dimensional matrix
     |
     |      :return: 3-dimensional NumPy array
     |      :rtype: ndarray(n,n,m)
     |
     |      Converts the value to a 3-dimensional NumPy array where the values are
     |      stacked along the third axis.  The first two dimensions are given by
     |      ``self.shape``.
     |
     |  strline(self, *args, **kwargs) -> 'str'
     |      Convert pose to compact single line string (superclass method)
     |
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: pose in string format
     |      :rtype: str
     |
     |      Convert pose in a compact single line format. If ``X`` has multiple
     |      values, the string has one pose per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.strline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.strline()
     |          >>> x.strline('angvec')
     |          >>> x.strline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.strline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __new__(cls, *args, **kwargs)
     |      Create the subclass instance (superclass method)
     |
     |      Create a new instance and call the superclass initializer to enable the
     |      ``UserList`` capabilities.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  N
     |      Dimension of the object's group (superclass property)
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
     |      This corresponds to the dimension of the space, 2D or 3D, to which these
     |      rotations or rigid-body motions apply.
     |
     |      Example::
     |
     |          >>> SE3().N
     |          3
     |          >>> SE2().N
     |          2
     |
     |  about
     |      Succinct summary of object type and length (superclass property)
     |
     |      :return: succinct summary
     |      :rtype: str
     |
     |      Displays the type and the number of elements in compact form, for
     |      example::
     |
     |          >>> x = SE3([SE3() for i in range(20)])
     |          >>> len(x)
     |          20
     |          >>> print(x.about)
     |          SE3[20]
     |
     |  isSE
     |      Test if object belongs to SE(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SE2 or SE3
     |      :rtype: bool
     |
     |  isSO
     |      Test if object belongs to SO(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SO2 or SO3
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __len__(self)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SO3(spatialmath.baseposematrix.BasePoseMatrix)
     |  SO3(arg=None, *, check=True)
     |
     |     SO(3) matrix class
     |
     |     This subclass represents rotations in 3D space.  Internally it is a 3x3
     |     orthogonal matrix belonging to the group SO(3).
     |
     |  .. inheritance-diagram:: spatialmath.pose3d.SO3
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  Method resolution order:
     |      SO3
     |      spatialmath.baseposematrix.BasePoseMatrix
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  UnitQuaternion(self) -> 'UnitQuaternion'
     |      SO3 as a unit quaternion instance
     |
     |      :return: a unit quaternion representation
     |      :rtype: UnitQuaternion instance
     |
     |      ``R.UnitQuaternion()`` is an ``UnitQuaternion`` instance representing the same rotation
     |      as the SO3 rotation ``R``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> SO3.Rz(0.3).UnitQuaternion()
     |
     |  __init__(self, arg=None, *, check=True)
     |      Construct new SO(3) object
     |
     |      :rtype: SO3 instance
     |
     |      There are multiple call signatures:
     |
     |      - ``SO3()`` is an ``SO3`` instance with one value -- a 3x3 identity
     |        matrix which corresponds to a null rotation
     |      - ``SO3(R)`` is an ``SO3`` instance with with the value ``R`` which is a
     |        3x3 numpy array representing an SO(3) rotation matrix.  If ``check``
     |        is ``True`` check the matrix belongs to SO(3).
     |      - ``SO3([R1, R2, ... RN])`` is an ``SO3`` instance wwith ``N`` values
     |        given by the elements ``Ri`` each of which is a 3x3 NumPy array
     |        representing an SO(3) matrix. If ``check`` is ``True`` check the
     |        matrix belongs to SO(3).
     |      - ``SO3([X1, X2, ... XN])`` is an ``SO3`` instance with ``N`` values
     |        given by the elements ``Xi`` each of which is an SO3 or SE3 instance.
     |
     |      :SymPy: supported
     |
     |  angdist(self, other: 'SO3', metric: 'int' = 6) -> 'Union[float, ndarray]'
     |      Angular distance metric between rotations
     |
     |      :param other: second rotation
     |      :type other: SO3 instance
     |      :param metric: metric, default is 6
     |      :type metric: int
     |      :raises TypeError: if other is not an SO3
     |      :return: angle in radians
     |      :rtype: float or ndarray
     |
     |      ``R1.angdist(R2)`` is the geodesic norm, or geodesic distance between two
     |      rotations.
     |
     |      Several metrics are supported, the first 5 are computed after conversion
     |      to unit quaternions.
     |
     |      ======   ===============================================================
     |      Metric   Details
     |      ======   ===============================================================
     |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
     |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      3        :math:`2 \tan^{-1} \| \q_1 - \q_2\| / \|\q_1 + \q_2\| \in [0, \pi/2]`
     |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
     |      5        :math:`\|I - \mat{R}_1 \mat{R}_2^T\| \in [0, 2]`
     |      6        :math:`\|\log \mat{R}_1 \mat{R}_2^T\| \in [0, \pi]`
     |      ======   ===============================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> R1 = SO3.Rx(0.3)
     |          >>> R2 = SO3.Ry(0.3)
     |          >>> print(R1.angdist(R1))
     |          >>> print(R1.angdist(R2))
     |
     |      .. note::
     |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
     |            numeric errors which push the argument of ``acos()`` marginally
     |            outside its domain [0, 1].
     |          - metrics 2 and 3 are equivalent, but 3 is more robust
     |
     |      :seealso: :func:`UnitQuaternion.angdist`
     |
     |  angvec(self, unit: 'str' = 'rad') -> 'Tuple[float, R3]'
     |      SO(3) or SE(3) as angle and rotation vector
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: :math:`(\theta, \hat{\bf v})`
     |      :rtype: float or ndarray(3)
     |
     |      ``x.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
     |      angle and a rotation axis.
     |
     |      By default the angle is in radians but can be changed setting `unit='deg'`.
     |
     |      .. note::
     |
     |          - If the input is SE(3) the translation component is ignored.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> R = SO3.Rx(0.3)
     |          >>> R.angvec()
     |
     |      :seealso: :meth:`eulervec` :meth:`AngVec` :meth:`~spatialmath.quaternion.UnitQuaternion.angvec` :meth:`~spatialmath.quaternion.AngVec`, :func:`~angvec2r`
     |
     |  eul(self, unit: 'str' = 'rad', flip: 'bool' = False) -> 'Union[R3, RNx3]'
     |      SO(3) or SE(3) as Euler angles
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of Euler angles
     |      :rtype: ndarray(3,), ndarray(n,3)
     |
     |      ``x.eul`` is the Euler angle representation of the rotation.  Euler angles are
     |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
     |      rotations about the Z, Y, Z axes respectively.
     |
     |      If ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(3,N)
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.tr2eul`
     |      :SymPy: not supported
     |
     |  eulervec(self) -> 'R3'
     |      SO(3) or SE(3) as Euler vector (exponential coordinates)
     |
     |      :return: :math:`\theta \hat{\bf v}`
     |      :rtype: ndarray(3)
     |
     |      ``x.eulervec()`` is the Euler vector (or exponential coordinates) which
     |      is related to angle-axis notation and is the product of the rotation
     |      angle and the rotation axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> R = SO3.Rx(0.3)
     |          >>> R.eulervec()
     |
     |      .. note::
     |
     |          - If the input is SE(3) the translation component is ignored.
     |
     |      :seealso: :meth:`angvec` :func:`~angvec2r`
     |
     |  inv(self) -> 'Self'
     |      Inverse of SO(3)
     |
     |      :return: inverse
     |      :rtype: SO2 instance
     |
     |      Efficiently compute the inverse of each of the SO(3) values taking into
     |      account the matrix structure.  For an SO(3) matrix the inverse is the
     |      transpose.
     |
     |  mean(self, tol: 'float' = 20) -> 'SO3'
     |      Mean of a set of SO(3) values
     |
     |      :param tol: iteration tolerance in units of eps, defaults to 20
     |      :type tol: float, optional
     |      :return: the mean rotation
     |      :rtype: :class:`SO3` instance.
     |
     |      Computes the Karcher mean of the set of SO(3) rotations within the :class:`SO3` instance.
     |
     |      :references:
     |          - `**Hartley, Trumpf** - "Rotation Averaging" - IJCV 2011 <https://users.cecs.anu.edu.au/~hartley/Papers/PDF/Hartley-Trumpf:Rotation-averaging:IJCV.pdf>`_, Algorithm 1, page 15.
     |          - `Karcher mean <https://en.wikipedia.org/wiki/Karcher_mean>`_
     |
     |      :seealso: :class:`SE3.mean`
     |
     |  rpy(self, unit: 'str' = 'rad', order: 'str' = 'zyx') -> 'Union[R3, RNx3]'
     |      SO(3) or SE(3) as roll-pitch-yaw angles
     |
     |      :param order: angle sequence order, default to 'zyx'
     |      :type order: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of roll-pitch-yaw angles
     |      :rtype: ndarray(3,), ndarray(n,3)
     |
     |      ``x.rpy`` is the roll-pitch-yaw angle representation of the rotation.  The angles are
     |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
     |      specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
     |            to the optic axis and x-axis parallel to the pixel rows.
     |
     |      If `len(x)` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(3,N)
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.RPY`, :func:`~spatialmath.base.transforms3d.tr2rpy`
     |      :SymPy: not supported
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  AngVec(theta, v, *, unit='rad') -> 'Self'
     |      Construct a new SO(3) rotation matrix from rotation angle and axis
     |
     |      :param theta: rotation
     |      :type theta: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param v: rotation axis, 3-vector
     |      :type v: array_like
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      ``SO3.AngVec(theta, V)`` is an SO(3) rotation defined by
     |      a rotation of ``THETA`` about the vector ``V``.
     |
     |      .. deprecated:: 0.9.8
     |          Use :meth:`AngleAxis` instead.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`spatialmath.base.transforms3d.angvec2r`
     |
     |  AngleAxis(theta: 'float', v: 'ArrayLike3', *, unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) rotation matrix from rotation angle and axis
     |
     |      :param theta: rotation
     |      :type theta: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param v: rotation axis, 3-vector
     |      :type v: array_like
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      ``SO3.AngleAxis(theta, V)`` is an SO(3) rotation defined by
     |      a rotation of ``THETA`` about the vector ``V``.
     |
     |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
     |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`spatialmath.base.transforms3d.angvec2r`
     |
     |  Eul(*angles, unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) from Euler angles
     |
     |      :param 𝚪: Euler angles
     |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      ``SO3.Eul(𝚪)`` is an SO(3) rotation defined by a 3-vector of Euler
     |        angles :math:`\Gamma = (\phi, \theta, \psi)` which correspond to
     |        consecutive rotations about the Z, Y, Z axes respectively. If ``𝚪``
     |        is an Nx3 matrix then the result is a sequence of rotations each
     |        defined by Euler angles corresponding to the rows of ``angles``.
     |
     |      ``SO3.Eul(φ, θ, ψ)`` as above but the angles are provided as three
     |        scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> SO3.Eul(0.1, 0.2, 0.3)
     |          >>> SO3.Eul([0.1, 0.2, 0.3])
     |          >>> SO3.Eul(10, 20, 30, unit="deg")
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.eul`, :func:`~spatialmath.pose3d.SE3.Eul`, :func:`~spatialmath.base.transforms3d.eul2r`
     |
     |  EulerVec(w) -> 'Self'
     |      Construct a new SO(3) rotation matrix from an Euler rotation vector
     |
     |      :param ω: rotation axis
     |      :type ω: 3-element array_like
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      ``SO3.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
     |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
     |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> SO3.EulerVec([0.5,0,0])
     |
     |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
     |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.angvec`, :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  Exp(S: 'Union[R3, RNx3]', check: 'bool' = True, so3: 'bool' = True) -> 'Self'
     |      Create an SO(3) rotation matrix from so(3)
     |
     |      :param S: Lie algebra so(3)
     |      :type S: ndarray(3,3), ndarray(n,3)
     |      :param check: check that passed matrix is valid so(3), default True
     |      :bool check: bool, optional
     |      :param so3: the input is interpretted as an so(3) matrix not a stack of three twists, default True
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      - ``SO3.Exp(S)`` is an SO(3) rotation defined by its Lie algebra
     |        which is a 3x3 so(3) matrix (skew symmetric)
     |      - ``SO3.Exp(t)`` is an SO(3) rotation defined by a 3-element twist
     |        vector (the unique elements of the so(3) skew-symmetric matrix)
     |      - ``SO3.Exp(T)`` is a sequence of SO(3) rotations defined by an Nx3 matrix
     |        of twist vectors, one per row.
     |
     |      .. note::
     |      - if :math:`\theta \eq 0` the result in an identity matrix
     |      - an input 3x3 matrix is ambiguous, it could be the first or third case above.  In this
     |        case the parameter `so3` is the decider.
     |
     |      :seealso: :func:`spatialmath.base.transforms3d.trexp`, :func:`spatialmath.base.transformsNd.skew`
     |
     |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'Self'
     |      Construct a new SO(3) from two vectors
     |
     |      :param o: 3-vector parallel to Y- axis
     |      :type o: array_like
     |      :param a: 3-vector parallel to the Z-axis
     |      :type o: array_like
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      ``SO3.OA(O, A)`` is an SO(3) rotation defined in terms of
     |      vectors parallel to the Y- and Z-axes of its reference frame.  In robotics these axes are
     |      respectively called the *orientation* and *approach* vectors defined such that
     |      R = [N, O, A] and N = O x A.
     |
     |      .. note::
     |
     |          - Only the ``A`` vector is guaranteed to have the same direction in the resulting
     |          rotation matrix
     |          - ``O`` and ``A`` do not have to be unit-length, they are normalized
     |          - ``O`` and ``A` do not have to be orthogonal, so long as they are not parallel
     |
     |      :seealso: :func:`spatialmath.base.transforms3d.oa2r`
     |
     |  RPY(*angles, unit='rad', order='zyx')
     |      Construct a new SO(3) from roll-pitch-yaw angles
     |
     |      :param angles: roll-pitch-yaw angles
     |      :type angles: array_like(3), array_like(n,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
     |      :type order: str
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      - ``SO3.RPY(angles)`` is an SO(3) rotation defined by a 3-vector of
     |        roll, pitch, yaw angles :math:`(\alpha, \beta, \gamma)`. If ``angles``
     |        is an Nx3 matrix then the result is a sequence of rotations each
     |        defined by RPY angles corresponding to the rows of angles. The angles
     |        correspond to successive rotations about the axes specified by
     |        ``order``:
     |
     |           - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |             then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
     |             and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
     |            to the optic axis and x-axis parallel to the pixel rows.
     |
     |      - ``SO3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
     |        scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> SO3.RPY(0.1, 0.2, 0.3)
     |          >>> SO3.RPY([0.1, 0.2, 0.3])
     |          >>> SO3.RPY(0.1, 0.2, 0.3, order='xyz')
     |          >>> SO3.RPY(10, 20, 30, unit="deg")
     |
     |
     |      :seealso: :func:`~spatialmath.pose3d.SE3.rpy`, :func:`~spatialmath.pose3d.SE3.RPY`, :func:`spatialmath.base.transforms3d.rpy2r`
     |
     |  Rand(N: 'int' = 1, *, theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) from random rotation
     |
     |      :param N: number of random rotations
     |      :type N: int
     |      :param theta_range: angular magnitude range [min,max], defaults to None.
     |      :type xrange: 2-element sequence, optional
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SO(3) rotation matrix
     |      :rtype: SO3 instance
     |
     |      - ``SO3.Rand()`` is a random SO(3) rotation.
     |      - ``SO3.Rand(N)`` is a sequence of N random rotations.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> x = SO3.Rand()
     |          >>> x
     |
     |      :seealso: :func:`spatialmath.quaternion.UnitQuaternion.Rand`
     |
     |  RotatedVector(v1: 'ArrayLike3', v2: 'ArrayLike3', tol=20) -> 'Self'
     |      Construct a new SO(3) from a vector and its rotated image
     |
     |      :param v1: initial vector
     |      :type v1: array_like(3)
     |      :param v2: vector after rotation
     |      :type v2: array_like(3)
     |      :param tol: tolerance for singularity in units of eps, defaults to 20
     |      :type tol: float
     |      :return: SO(3) rotation
     |      :rtype: :class:`SO3` instance
     |
     |      ``SO3.RotatedVector(v1, v2)`` is an SO(3) rotation defined in terms of
     |      two vectors. The rotation takes vector ``v1`` to ``v2``.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> v1 = [1, 2, 3]
     |          >>> v2 = SO3.Eul(0.3, 0.4, 0.5) * v1
     |          >>> print(v2)
     |          >>> R = SO3.RotatedVector(v1, v2)
     |          >>> print(R)
     |          >>> print(R * v1)
     |
     |      .. note:: The vectors do not have to be unit-length.
     |
     |  Rx(theta: 'float', unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) from X-axis rotation
     |
     |      :param θ: rotation angle about the X-axis
     |      :type θ: float or array_like
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      - ``SE3.Rx(θ)`` is an SO(3) rotation of ``θ`` radians about the x-axis
     |      - ``SE3.Rx(θ, "deg")`` as above but ``θ`` is in degrees
     |
     |      If ``theta`` is an array then the result is a sequence of rotations defined by consecutive
     |      elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> import numpy as np
     |          >>> x = SO3.Rx(np.linspace(0, math.pi, 20))
     |          >>> len(x)
     |          >>> x[7]
     |
     |  Ry(theta, unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) from Y-axis rotation
     |
     |      :param θ: rotation angle about Y-axis
     |      :type θ: float or array_like
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      - ``SO3.Ry(θ)`` is an SO(3) rotation of ``θ`` radians about the y-axis
     |      - ``SO3.Ry(θ, "deg")`` as above but ``θ`` is in degrees
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined by consecutive
     |      elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> import numpy as np
     |          >>> x = SO3.Ry(np.linspace(0, math.pi, 20))
     |          >>> len(x)
     |          >>> x[7]
     |
     |  Rz(theta, unit: 'str' = 'rad') -> 'Self'
     |      Construct a new SO(3) from Z-axis rotation
     |
     |      :param θ: rotation angle about Z-axis
     |      :type θ: float or array_like
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: SO(3) rotation
     |      :rtype: SO3 instance
     |
     |      - ``SO3.Rz(θ)`` is an SO(3) rotation of ``θ`` radians about the z-axis
     |      - ``SO3.Rz(θ, "deg")`` as above but ``θ`` is in degrees
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined by consecutive
     |      elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> import numpy as np
     |          >>> x = SO3.Rz(np.linspace(0, math.pi, 20))
     |          >>> len(x)
     |          >>> x[7]
     |
     |  TwoVectors(x: 'Optional[Union[str, ArrayLike3]]' = None, y: 'Optional[Union[str, ArrayLike3]]' = None, z: 'Optional[Union[str, ArrayLike3]]' = None) -> 'Self'
     |      Construct a new SO(3) from any two vectors
     |
     |      :param x: new x-axis, defaults to None
     |      :type x: str, array_like(3), optional
     |      :param y: new y-axis, defaults to None
     |      :type y: str, array_like(3), optional
     |      :param z: new z-axis, defaults to None
     |      :type z: str, array_like(3), optional
     |
     |      Create a rotation by defining the direction of two of the new
     |      axes in terms of the old axes.  Axes are denoted by strings ``"x"``,
     |      ``"y"``, ``"z"``, ``"-x"``, ``"-y"``, ``"-z"``.
     |
     |      The directions can also be specified by 3-element vectors. If the vectors are not orthogonal,
     |      they will orthogonalized w.r.t. the first available dimension. I.e. if x is available, it will be
     |      normalized and the remaining vector will be orthogonalized w.r.t. x, else, y will be normalized
     |      and z will be orthogonalized w.r.t. y.
     |
     |      To create a rotation where the new frame has its x-axis in -z-direction
     |      of the previous frame, and its z-axis in the x-direction of the previous
     |      frame is::
     |
     |          >>> SO3.TwoVectors(x='-z', z='x')
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x: 'NDArray', check: 'bool' = True) -> 'bool'
     |      Test if matrix is valid SO(3)
     |
     |      :param x: matrix to test
     |      :type x: numpy.ndarray
     |      :return: ``True`` if the matrix is a valid element of SO(3), ie. it is a 3x3
     |          orthonormal matrix with determinant of +1.
     |      :rtype: bool
     |
     |      :seealso: :func:`~spatialmath.base.transform3d.isrot`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  R
     |      SO(3) or SE(3) as rotation matrix
     |
     |      :return: rotational component
     |      :rtype: ndarray(3,3)
     |
     |      ``x.R`` is the rotation matrix component of ``x`` as an array with
     |      shape (3,3). If ``len(x) > 1``, return an array with shape=(N,3,3).
     |
     |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
     |          ``x[i]``. This is different to the MATLAB version where the i'th
     |          rotation matrix is ``x(:,:,i)``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO3
     |          >>> x = SO3.Rx(0.3)
     |          >>> x.R
     |
     |      :SymPy: supported
     |
     |  a
     |      Approach vector of SO(3) or SE(3)
     |
     |      :return: approach vector
     |      :rtype: ndarray(3)
     |
     |      This is the third column of the rotation submatrix, sometimes called the
     |      *approach vector*.  It is parallel to the z-axis of the frame defined by
     |      this pose.
     |
     |  n
     |      Normal vector of SO(3) or SE(3)
     |
     |      :return: normal vector
     |      :rtype: ndarray(3)
     |
     |      This is the first column of the rotation submatrix, sometimes called the
     |      *normal vector*.  It is parallel to the x-axis of the frame defined by
     |      this pose.
     |
     |  o
     |      Orientation vector of SO(3) or SE(3)
     |
     |      :return: orientation vector
     |      :rtype: ndarray(3)
     |
     |      This is the second column of the rotation submatrix, sometimes called
     |      the *orientation vector*.  It is parallel to the y-axis of the frame
     |      defined by this pose.
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (3,3)
     |      :rtype: tuple
     |
     |      Each value within the ``SO3`` instance is a NumPy array of this shape.
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __add__(left, right)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Add the elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X + Y`` is the element-wise sum of the matrix value of ``X`` and ``Y``
     |      - ``X + s`` is the element-wise sum of the matrix value of ``X`` and scalar ``s``
     |      - ``s + X`` is the element-wise sum of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ========================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ========================
     |      Pose             Pose             NxN matrix   element-wise matrix sum
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ========================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar + Pose is handled by :meth:`__radd__`
     |          #. Addition is commutative
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose addition either or both operands may hold more than one value which
     |      results in the sum holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``sum = left + right``
     |       1          M             M    ``sum[i] = left + right[i]``
     |       N          1             M    ``sum[i] = left[i] + right``
     |       M          M             M    ``sum[i] = left[i] + right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __eq__(left, right: 'Self') -> 'bool'
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for equality
     |
     |      ``X == Y`` is true of the poses are of the same type and numerically
     |      equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the equality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``eq = left == right``
     |       1          M             M    ``eq[i] = left == right[i]``
     |       N          1             M    ``eq[i] = left[i] == right``
     |       M          M             M    ``eq[i] = left[i] == right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __iadd__(left, right)
     |      Overloaded ``+=`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X += Y`` adds the matrix values of ``X`` and ``Y`` and places the result in ``X``
     |      - ``X += s`` elementwise addition of the matrix elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__add__``
     |
     |  __imul__(left, right)
     |      Overloaded ``*=`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X *= Y`` compounds the poses ``X`` and ``Y`` and places the result in ``X``
     |      - ``X *= s`` performs elementwise multiplication of the elements of ``X``
     |        and ``s`` and places the result in ``X``
     |
     |      :seealso: ``__mul__``
     |
     |  __isub__(left, right: 'Self')
     |      Overloaded ``-=`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises: ValueError
     |
     |      - ``X -= Y`` is the element-wise difference of the matrix value of ``X``
     |        and ``Y`` and places the result in ``X``
     |      - ``X -= s`` is the element-wise difference of the matrix value of ``X``
     |        and the scalar ``s`` and places the result in ``X``
     |
     |      :seealso: ``__sub__``
     |
     |  __itruediv__(left, right)
     |      Overloaded ``/=`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X /= Y`` compounds the poses ``X`` and ``Y.inv()`` and places the result in ``X``
     |      - ``X /= s`` performs elementwise division of the elements of ``X``
     |        by ``s`` and places the result in ``X``
     |
     |      :seealso: ``__truediv__``
     |
     |  __matmul__(left, right)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :return: Product of two operands with normalization
     |      :rtype: Pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      - ``X @ Y`` compounds the poses ``X`` and ``Y`` and normalizes the result
     |      - ``X @= Y`` compounds the poses ``X`` and ``Y``, normalizes the result,
     |        and places the result in ``X``
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally
     |          update over many cycles.
     |
     |      :seealso: :func:`__mul__`, :func:`~spatialmath.base.trnorm`
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Pose composition, scaling or vector transformation:
     |
     |      - ``X * Y`` compounds the poses ``X`` and ``Y``
     |      - ``X * s`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs element-wise multiplication of the elements of ``X`` by ``s``
     |      - ``X * v`` linear transformation of the vector ``v`` where ``v`` is array-like
     |
     |      ==============   ==============   ===========  ======================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ======================
     |      Pose             Pose             Pose         matrix product
     |      Pose             scalar           NxN matrix   element-wise product
     |      scalar           Pose             NxN matrix   element-wise product
     |      Pose             N-vector         N-vector     vector transform
     |      Pose             NxM matrix       NxM matrix   transform each column
     |      ==============   ==============   ===========  ======================
     |
     |      .. note::
     |
     |          #. Pose is an ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar x Pose is handled by __rmul__`
     |          #. Scalar multiplication is commutative but the result is not a group
     |             operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * SE3.Ry(pi/2)
     |          SE3(array([[0., 0., 1., 0.],
     |                  [1., 0., 0., 0.],
     |                  [0., 1., 0., 0.],
     |                  [0., 0., 0., 1.]]))
     |          >>> SE3.Rx(pi/2) * 2
     |          array([[ 2.0000000e+00,  0.0000000e+00,  0.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  1.2246468e-16, -2.0000000e+00,  0.0000000e+00],
     |                 [ 0.0000000e+00,  2.0000000e+00,  1.2246468e-16,  0.0000000e+00],
     |                 [ 0.0000000e+00,  0.0000000e+00,  0.0000000e+00,  2.0000000e+00]])
     |
     |      For vector transformation there are three cases:
     |
     |      =========  ===========  =====  ==========================
     |            Multiplicands             Product
     |      ----------------------  ---------------------------------
     |      len(left)  right.shape  shape  operation
     |      =========  ===========  =====  ==========================
     |      1          (N,)         (N,)   vector transformation
     |      M          (N,)         (N,M)  vector transformations
     |      1          (N,M)        (N,M)  column transformation
     |      =========  ===========  =====  ==========================
     |
     |      .. note::
     |          - The vector is an array-like, a 1D NumPy array or a list/tuple
     |          - For the ``SE2`` and ``SE3`` case the vectors are converted to homogeneous
     |            form, transformed, then converted back to Euclidean form.
     |
     |      Example::
     |
     |          >>> SE3.Rx(pi/2) * [0, 1, 0]
     |          array([0.000000e+00, 6.123234e-17, 1.000000e+00])
     |          >>> SE3.Rx(pi/2) * np.r_[0, 0, 1]
     |          array([ 0.000000e+00, -1.000000e+00,  6.123234e-17])
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :return: Inequality of two operands
     |      :rtype: bool or list of bool
     |
     |      Test two poses for inequality
     |
     |      - ``X != Y`` is true of the poses are of the same type but not numerically
     |        equal.
     |
     |      If either or both operands may hold more than one value which
     |      results in the inequality test holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``ne = left != right``
     |       1          M             M    ``ne[i] = left != right[i]``
     |       N          1             M    ``ne[i] = left[i] != right``
     |       M          M             M    ``ne[i] = left[i] != right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __pow__(self, n: 'int') -> 'Self'
     |      Overloaded ``**`` operator (superclass method)
     |
     |      :param n: exponent
     |      :type n: int
     |      :return: pose to the power ``n``
     |      :rtype: pose instance
     |
     |      ``X**n`` raise all values held in `X` to the specified power using repeated
     |      multiplication.  If ``n`` < 0 then the result is inverted.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3.Rx(0.1) ** 2
     |          >>> SE3.Rx([0, 0.1]) ** 2
     |
     |  __radd__(right, left)
     |      Overloaded ``+`` operator (superclass method)
     |
     |      :return: Sum of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s + X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__add__`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> repr(x)
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: Product of two operands
     |      :rtype: Pose instance or NumPy array
     |      :raises NotImplemented: for incompatible arguments
     |
     |      Left-multiplication
     |
     |      - ``s * X`` where ``s`` is a scalar, performs elementwise multiplication of the
     |        elements of ``X`` by ``s`` and the result is a NumPy array.
     |      - ``A * X`` where ``A`` is a conforming matrix, performs matrix multiplication
     |        of ``A`` and ``X`` and the result is a NumPy array.
     |
     |      :seealso: :func:`__mul__`
     |
     |  __rsub__(right, left: 'Self')
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |      Left-addition by a scalar
     |
     |      - ``s - X`` performs elementwise addition of the elements of ``X`` and ``s``
     |
     |      :seealso: :meth:`__sub__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of pose (superclass method)
     |
     |      :return: readable representation of the pose
     |      :rtype: str
     |
     |      Convert the pose's matrix value to a simple grid of numbers.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x)
     |
     |      Notes:
     |
     |          - By default, the output is colorised for an ANSI terminal console:
     |
     |              * red: rotational elements
     |              * blue: translational elements
     |              * white: constant elements
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: Difference of two operands
     |      :rtype: NumPy array, shape=(N,N)
     |      :raises ValueError: for incompatible arguments
     |
     |
     |      Subtract elements of two poses.  This is not a group operation so the
     |      result is a matrix not a pose class.
     |
     |      - ``X - Y`` is the element-wise difference of the matrix value of ``X`` and ``Y``
     |      - ``X - s`` is the element-wise difference of the matrix value of ``X`` and the scalar ``s``
     |      - ``s - X`` is the element-wise difference of the scalar ``s`` and the matrix value of ``X``
     |
     |      ==============   ==============   ===========  ==============================
     |                 Operands                   Sum
     |      -------------------------------   -------------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  ==============================
     |      Pose             Pose             NxN matrix   element-wise matrix difference
     |      Pose             scalar           NxN matrix   element-wise sum
     |      scalar           Pose             NxN matrix   element-wise sum
     |      ==============   ==============   ===========  ==============================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. scalar - Pose is handled by :meth:`__rsub__`
     |          #. Any other input combinations result in a ``ValueError``.
     |
     |      For pose subtraction either or both operands may hold more than one value which
     |      results in the difference holding more than one value according to:
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``diff = left - right``
     |       1          M             M    ``diff[i] = left - right[i]``
     |       N          1             M    ``diff[i] = left[i] - right``
     |       M          M             M    ``diff[i] = left[i]  right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __truediv__(left, right)
     |      Overloaded ``/`` operator (superclass method)
     |
     |      :return: Product of right operand and inverse of left operand
     |      :rtype: pose instance or NumPy array
     |      :raises ValueError: for incompatible arguments
     |
     |      Pose composition or scaling:
     |
     |      - ``X / Y`` compounds the poses ``X`` and ``Y.inv()``
     |      - ``X / s`` performs elementwise division of the elements of ``X`` by ``s``
     |
     |      ==============   ==============   ===========  =========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   --------------------------------------
     |          left             right            type           operation
     |      ==============   ==============   ===========  =========================
     |      Pose             Pose             Pose         matrix product by inverse
     |      Pose             scalar           NxN matrix   element-wise division
     |      ==============   ==============   ===========  =========================
     |
     |      .. note::
     |
     |          #. Pose is ``SO2``, ``SE2``, ``SO3`` or ``SE3`` instance
     |          #. N is 2 for ``SO2``, ``SE2``; 3 for ``SO3`` or ``SE3``
     |          #. Scalar multiplication is not a group operation so the result will
     |             be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |  animate(self, *args, start=None, **kwargs) -> 'None'
     |      Plot pose object as an animated coordinate frame (superclass method)
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: same as ``self``
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.animate()`` displays the pose ``X`` as a coordinate frame moving
     |        from the origin in either 2D or 3D.  There are many options, see the
     |        links below.
     |      - ``X.animate(*args, start=X1)`` displays the pose ``X`` as a coordinate
     |        frame moving from pose ``X1``, in either 2D or 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=SE3.Ry(0.2))
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.tranimate`, :func:`~spatialmath.base.transforms2d.tranimate2`
     |
     |  conjugation(self, A: 'NDArray') -> 'NDArray'
     |      Matrix conjugation
     |
     |      :param A: matrix to conjugate
     |      :type A: ndarray
     |      :return: conjugated matrix
     |      :rtype: ndarray
     |
     |      Compute the conjugation :math:`\mat{X} \mat{A} \mat{X}^{-1}` where :math:`\mat{X}`
     |      is the current object.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SO2
     |          >>> import numpy as np
     |          >>> R = SO2(0.5)
     |          >>> A = np.array([[10, 0], [0, 1]])
     |          >>> print(R * A * R.inv())
     |          >>> print(R.conjugation(A))
     |
     |  det(self) -> 'Tuple[float, Rn]'
     |      Determinant of rotational component (superclass method)
     |
     |      :return: Determinant of rotational component
     |      :rtype: float or NumPy array
     |
     |      ``x.det()`` is the determinant of the rotation component of the values
     |      of ``x``.
     |
     |      Example::
     |
     |          >>> x=SE3.Rand()
     |          >>> x.det()
     |          1.0000000000000004
     |          >>> x=SE3.Rand(N=2)
     |          >>> x.det()
     |          [0.9999999999999997, 1.0000000000000002]
     |
     |      :SymPy: not supported
     |
     |  interp(self, end: 'Optional[bool]' = None, s: 'Union[int, float]' = None, shortest: 'bool' = True) -> 'Self'
     |      Interpolate between poses (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :param shortest: take the shortest path along the great circle for the rotation
     |      :type shortest: bool, default to True
     |      :return: interpolated pose
     |      :rtype: same as ``self``
     |
     |      - ``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.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> x = SE3(-1, -2, 0) * SE3.Rx(-0.3)
     |          >>> y = SE3(1, 2, 0) * SE3.Rx(0.3)
     |          >>> x.interp(y, 0)    # this is x
     |          >>> x.interp(y, 1)    # this is y
     |          >>> x.interp(y, 0.5)  # this is in between
     |          >>> z = x.interp(y, 11)  # in 11 steps
     |          >>> len(z)
     |          >>> z[0]              # this is x
     |          >>> z[5]              # this is in between
     |
     |      .. note::
     |
     |          - 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
     |
     |  interp1(self, s: 'float' = None) -> 'Self'
     |      Interpolate pose (superclass method)
     |
     |      :param end: final pose
     |      :type end: same as ``self``
     |      :param s: interpolation coefficient, range 0 to 1
     |      :type s: array_like
     |      :return: interpolated pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.interp(s)`` interpolates pose between identity when s=0, and X when s=1.
     |
     |          ======  ======  ===========  ===============================
     |          len(X)  len(s)  len(result)  Result
     |          ======  ======  ===========  ===============================
     |          1       1       1            Y = interp(X, s)
     |          M       1       M            Y[i] = interp(X[i], s)
     |          1       M       M            Y[i] = interp(X, s[i])
     |          ======  ======  ===========  ===============================
     |
     |      Example::
     |
     |          >>> x = SE3.Rx(0.3)
     |          >>> print(x.interp(0))
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |          >>> print(x.interp(1))
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.95533649, -0.29552021,  0.        ],
     |                     [ 0.        ,  0.29552021,  0.95533649,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |          >>> y = x.interp(x, np.linspace(0, 1, 10))
     |          >>> len(y)
     |          10
     |          >>> y[5]
     |          SE3(array([[ 1.        ,  0.        ,  0.        ,  0.        ],
     |                     [ 0.        ,  0.98614323, -0.16589613,  0.        ],
     |                     [ 0.        ,  0.16589613,  0.98614323,  0.        ],
     |                     [ 0.        ,  0.        ,  0.        ,  1.        ]]))
     |
     |      Notes:
     |
     |      #. For SO3 and SE3 rotation is interpolated using quaternion spherical linear interpolation (slerp).
     |
     |      :seealso: :func:`interp`, :func:`~spatialmath.base.transforms3d.trinterp`, :func:`~spatialmath.base.quaternions.qslerp`, :func:`~spatialmath.smb.transforms2d.trinterp2`
     |
     |      :SymPy: not supported
     |
     |  ishom(self) -> 'bool'
     |      Test if object belongs to SE(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          True
     |
     |  ishom2(self) -> 'bool'
     |      Test if object belongs to SE(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SE2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SE2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          False
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          True
     |
     |  isrot(self) -> 'bool'
     |      Test if object belongs to SO(3) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO3
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO3)``.
     |
     |      Example::
     |
     |          >>> x = SO3()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE3()
     |          >>> x.isrot()
     |          False
     |
     |  isrot2(self) -> 'bool'
     |      Test if object belongs to SO(2) group (superclass method)
     |
     |      :return: ``True`` if object is instance of SO2
     |      :rtype: bool
     |
     |      For compatibility with Spatial Math Toolbox for MATLAB.
     |      In Python use ``isinstance(x, SO2)``.
     |
     |      Example::
     |
     |          >>> x = SO2()
     |          >>> x.isrot()
     |          True
     |          >>> x = SE2()
     |          >>> x.isrot()
     |          False
     |
     |  log(self, twist: 'Optional[bool]' = False) -> 'Union[NDArray, List[NDArray]]'
     |      Logarithm of pose (superclass method)
     |
     |      :return: logarithm
     |      :rtype: ndarray
     |      :raises: ValueError
     |
     |      An efficient closed-form solution of the matrix logarithm.
     |
     |      =====  ======  ===============================
     |      Input         Output
     |      -----  ---------------------------------------
     |      Pose   Shape   Structure
     |      =====  ======  ===============================
     |      SO2    (2,2)   skew-symmetric SE2    (3,3)   augmented skew-symmetric
     |      SO3    (3,3)   skew-symmetric SE3    (4,4)   augmented skew-symmetric
     |      =====  ======  ===============================
     |
     |      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. ]])
     |
     |
     |      :seealso: :func:`~spatialmath.base.transforms2d.trlog2`,
     |      :func:`~spatialmath.base.transforms3d.trlog`
     |
     |      :SymPy: not supported
     |
     |  norm(self) -> 'Self'
     |      Normalize pose (superclass method)
     |
     |      :return: pose
     |      :rtype: SO2, SE2, SO3, SE3 instance
     |
     |      - ``X.norm()`` is an equivalent pose object but the rotational matrix
     |        part of all values has been adjusted to ensure it is a proper orthogonal
     |        matrix rotation.
     |
     |      Example::
     |
     |          >>> x = SE3()
     |          >>> y = x.norm()
     |          >>> y
     |          SE3(array([[1., 0., 0., 0.],
     |                     [0., 1., 0., 0.],
     |                     [0., 0., 1., 0.],
     |                     [0., 0., 0., 1.]]))
     |
     |      Notes:
     |
     |      #. Only the direction of A vector (the z-axis) is unchanged.
     |      #. Used to prevent finite word length arithmetic causing transforms to
     |         become 'unnormalized'.
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trnorm`, :func:`~spatialmath.base.transforms2d.trnorm2`
     |
     |  plot(self, *args, **kwargs) -> 'None'
     |      Plot pose object as a coordinate frame (superclass method)
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``X.plot()`` displays the pose ``X`` as a coordinate frame in either
     |        2D or 3D.  There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = SE3.Rx(0.3)
     |          >>> X.plot(frame='A', color='green')
     |
     |      .. plot::
     |
     |          from spatialmath import SE3
     |          X = SE3.Rx(0.3)
     |          X.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`, :func:`~spatialmath.base.transforms2d.trplot2`
     |
     |  print(self, label: 'Optional[str]' = None, file: 'Optional[TextIO]' = None) -> 'None'
     |      Print pose as a matrix (superclass method)
     |
     |      :param label: label to print before the matrix, defaults to None
     |      :type label: str, optional
     |      :param file: file to write to, defaults to None
     |      :type file: file object, optional
     |
     |      Print the pose as a matrix, with an optional line beforehand.  By default
     |      the matrix is printed to stdout.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> SE3().print()
     |          >>> SE3().print("pose is:")
     |
     |      :seealso: :meth:`printline` :meth:`strline`
     |
     |  printline(self, *args, **kwargs) -> 'None'
     |      Print pose in compact single line format (superclass method)
     |
     |      :param arg: value for orient option, optional
     |      :type arg: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param file: file to write formatted string to. [default, stdout]
     |      :type file: file object
     |
     |      Print pose in a compact single line format. If ``X`` has multiple
     |      values, print one per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.printline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.printline()
     |          >>> x.printline('angvec')
     |          >>> x.printline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.printline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`strline` :func:`trprint`, :func:`trprint2`
     |
     |  prod(self, norm=False, check=True) -> 'Self'
     |      Product of elements (superclass method)
     |
     |      :param norm: normalize the product, defaults to False
     |      :type norm: bool, optional
     |      :param check: check that computed matrix is valid member of group, default True
     |      :bool check: bool, optional
     |      :return: Product of elements
     |      :rtype: pose instance
     |
     |      ``x.prod()`` is the product of the values held by ``x``, ie.
     |      :math:`\prod_i^N T_i`.
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3
     |          >>> x = SE3.Rx([0, 0.1, 0.2, 0.3])
     |          >>> x.prod()
     |
     |      .. note:: When compounding many transformations the product may become
     |          denormalized resulting in a result that is not a proper member of the
     |          group.  You can either disable membership checking by ``check=False``
     |          which is risky, or normalize the result by ``norm=True``.
     |
     |  simplify(self) -> 'Self'
     |      Symbolically simplify matrix values (superclass method)
     |
     |      :return: pose with symbolic elements
     |      :rtype: pose instance
     |
     |      Apply symbolic simplification to every element of every value in the
     |      pose instance.
     |
     |      Example::
     |
     |          >>> a = SE3.Rx(sympy.symbols('theta'))
     |          >>> b = a * a
     |          >>> b
     |          SE3(array([[1, 0, 0, 0.0],
     |          [0, -sin(theta)**2 + cos(theta)**2, -2*sin(theta)*cos(theta), 0],
     |          [0, 2*sin(theta)*cos(theta), -sin(theta)**2 + cos(theta)**2, 0],
     |          [0.0, 0, 0, 1.0]], dtype=object)
     |          >>> b.simplify()
     |          SE3(array([[1, 0, 0, 0],
     |          [0, cos(2*theta), -sin(2*theta), 0],
     |          [0, sin(2*theta), cos(2*theta), 0],
     |          [0, 0, 0, 1.00000000000000]], dtype=object))
     |
     |      .. todo:: No need to simplify the constants in bottom row
     |
     |      :SymPy: supported
     |
     |  stack(self) -> 'NDArray'
     |      Convert to 3-dimensional matrix
     |
     |      :return: 3-dimensional NumPy array
     |      :rtype: ndarray(n,n,m)
     |
     |      Converts the value to a 3-dimensional NumPy array where the values are
     |      stacked along the third axis.  The first two dimensions are given by
     |      ``self.shape``.
     |
     |  strline(self, *args, **kwargs) -> 'str'
     |      Convert pose to compact single line string (superclass method)
     |
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param fmt: conversion format for each number as used by ``format()``
     |      :type fmt: str
     |      :param label: text label to put at start of line
     |      :type label: str
     |      :param orient: 3-angle convention to use, optional, ``SO3`` and ``SE3``
     |                     only
     |      :type orient: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: pose in string format
     |      :rtype: str
     |
     |      Convert pose in a compact single line format. If ``X`` has multiple
     |      values, the string has one pose per line.
     |
     |      Orientation can be displayed in various formats:
     |
     |      =============   =================================================
     |      ``orient``      description
     |      =============   =================================================
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order [default]
     |      ``'rpy/yxz'``   roll-pitch-yaw angles in YXZ axis order
     |      ``'rpy/zyx'``   roll-pitch-yaw angles in ZYX axis order
     |      ``'eul'``       Euler angles in ZYZ axis order
     |      ``'angvec'``    angle and axis
     |      =============   =================================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, SE3
     |          >>> x = SE3.Rx(0.3)
     |          >>> x.strline()
     |          >>> x = SE3.Rx([0.2, 0.3])
     |          >>> x.strline()
     |          >>> x.strline('angvec')
     |          >>> x.strline(orient='angvec', fmt="{:.6f}")
     |          >>> x = SE2(1, 2, 0.3)
     |          >>> x.strline()
     |
     |      .. note::
     |          - Default formatting is for compact display of data
     |          - For tabular data set ``fmt`` to a fixed width format such as
     |            ``fmt='{:.3g}'``
     |
     |      :seealso: :meth:`printline` :func:`trprint`, :func:`trprint2`
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __new__(cls, *args, **kwargs)
     |      Create the subclass instance (superclass method)
     |
     |      Create a new instance and call the superclass initializer to enable the
     |      ``UserList`` capabilities.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  N
     |      Dimension of the object's group (superclass property)
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``SO2`` or ``SE2``, and 3 for ``SO3`` or ``SE3``.
     |      This corresponds to the dimension of the space, 2D or 3D, to which these
     |      rotations or rigid-body motions apply.
     |
     |      Example::
     |
     |          >>> SE3().N
     |          3
     |          >>> SE2().N
     |          2
     |
     |  about
     |      Succinct summary of object type and length (superclass property)
     |
     |      :return: succinct summary
     |      :rtype: str
     |
     |      Displays the type and the number of elements in compact form, for
     |      example::
     |
     |          >>> x = SE3([SE3() for i in range(20)])
     |          >>> len(x)
     |          20
     |          >>> print(x.about)
     |          SE3[20]
     |
     |  isSE
     |      Test if object belongs to SE(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SE2 or SE3
     |      :rtype: bool
     |
     |  isSO
     |      Test if object belongs to SO(n) group (superclass property)
     |
     |      :param self: object to test
     |      :type self: SO2, SE2, SO3, SE3 instance
     |      :return: ``True`` if object is instance of SO2 or SO3
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from spatialmath.baseposematrix.BasePoseMatrix:
     |
     |  __array_ufunc__ = None
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __len__(self)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike4 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike6 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLikePure = typing.Union[typing.List[float], typing.Tuple[fl...nda...
    Callable = typing.Callable
        Deprecated alias to collections.abc.Callable.

        Callable[[int], str] signifies a function that takes a single
        parameter of type int and returns a str.

        The subscription syntax must always be used with exactly two
        values: the argument list and the return type.
        The argument list must be a list of types, a ParamSpec,
        Concatenate or ellipsis. The return type must be a single type.

        There is no syntax to indicate optional or keyword arguments;
        such function types are rarely used as callback types.

    Color = typing.Union[str, typing.List[float], typing.Tup...typing.Lite...
    DTypeLike = typing.Union[numpy.dtype[typing.Any], NoneType, ...e_like....
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    L = typing.Literal
        Special typing form to define literal types (a.k.a. value types).

        This form can be used to indicate to type checkers that the corresponding
        variable or function parameter has a value equivalent to the provided
        literal (or one of several literals)::

            def validate_simple(data: Any) -> Literal[True]:  # always returns True
                ...

            MODE = Literal['r', 'rb', 'w', 'wb']
            def open_helper(file: str, mode: MODE) -> str:
                ...

            open_helper('/some/path', 'r')  # Passes type check
            open_helper('/other/path', 'typo')  # Error in type checker

        Literal[...] cannot be subclassed. At runtime, an arbitrary value
        is allowed as type argument to Literal[...], but type checkers may
        impose restrictions.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Points3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    QuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy...
    R1 = numpy.ndarray[typing.Tuple[typing.Literal[1]], numpy.dtype[numpy....
    R1x1 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[1]...
    R1x2 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[2]...
    R1x3 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[3]...
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R2x1 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[1]...
    R2x2 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]...
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R3x1 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[1]...
    R3x3 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]...
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    R4x4 = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]...
    R6 = numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy....
    R6x6 = numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]...
    R8 = numpy.ndarray[typing.Tuple[typing.Literal[8]], numpy.dtype[numpy....
    R8x8 = numpy.ndarray[typing.Tuple[typing.Literal[8], typing.Literal[8]...
    RNx3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Rn = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.Literal...
    SE2Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SE3Array = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Litera...
    SEnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    SO2Array = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Litera...
    SO3Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SOnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    TYPE_CHECKING = False
    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Type = typing.Type
        Deprecated alias to builtins.type.

        builtins.type or typing.Type can be used to annotate class objects.
        For example, suppose we have the following classes::

            class User: ...  # Abstract base for User classes
            class BasicUser(User): ...
            class ProUser(User): ...
            class TeamUser(User): ...

        And a function that takes a class argument that's a subclass of
        User and returns an instance of the corresponding class::

            def new_user[U](user_class: Type[U]) -> U:
                user = user_class()
                # (Here we could write the user object to a database)
                return user

            joe = new_user(BasicUser)

        At this point the type checker knows that joe has type BasicUser.

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

    UnitQuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], n...
    se2Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    se3Array = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[...
    senArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    so2Array = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[...
    so3Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    sonArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\pose3d.py

spatialmath-python.quaternion
Python Library Documentation: module spatialmath.quaternion in spatialmath

NAME
    spatialmath.quaternion - Classes to abstract quaternions and unit-quaternions.

DESCRIPTION
    To use::

        from spatialmath.quaternion import *
        T = UnitQuaternion.Rx(0.3)

        import spatialmath as sm
        T = sm.UnitQuaternion.Rx(0.3)

     .. inheritance-diagram:: spatialmath.quaternion
        :top-classes: collections.UserList
        :parts: 1

CLASSES
    spatialmath.baseposelist.BasePoseList(collections.UserList, abc.ABC)
        Quaternion
            UnitQuaternion

    class Quaternion(spatialmath.baseposelist.BasePoseList)
     |  Quaternion(s: 'Any' = None, v=None, check: 'Optional[bool]' = True)
     |
     |  Quaternion class
     |
     |  A quaternion can be considered an ordered pair :math:`(s, \vec{v})`
     |  where :math:`s \in \mathbb{R}` is the *scalar* part and :math:`\vec{v} = (v_x, v_y, v_z) \in \mathbb{R}^3`
     |  is the *vector* part and is often written as
     |
     |  .. math:: \q = s \langle v_x, v_y, v_z \rangle
     |
     |  .. inheritance-diagram:: spatialmath.quaternion.Quaternion
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  Method resolution order:
     |      Quaternion
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __add__(left, right: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``+`` operator
     |
     |      :return: sum
     |      :rtype: Quaternion, UnitQuaternion
     |      :raises: ValueError
     |
     |      ==============   ==============   ==============  ===================
     |                 Operands                            Sum
     |      -------------------------------   -----------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ===================
     |      Quaternion       Quaternion       Quaternion      elementwise sum
     |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
     |      Quaternion       scalar           Quaternion      add to each element
     |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
     |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
     |      UnitQuaternion   scalar           Quaternion      add to each element
     |      ==============   ==============   ==============  ===================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``sum = left + right``
     |       1      N       N    ``sum[i] = left + right[i]``
     |       N      1       N    ``sum[i] = left[i] + right``
     |       N      N       N    ``sum[i] = left[i] + right[i]``
     |       N      M       -    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      A scalar of length N is a list, tuple or numpy array.
     |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]) + Quaternion([5,6,7,8])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([1,2,3,4])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  __eq__(left, right: 'Quaternion') -> 'bool'
     |      Overloaded ``==`` operator
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |      ``q1 == q2`` is True if ``q1` is elementwise equal to ``q2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q1 = Quaternion([1,2,3,4])
     |          >>> q2 = Quaternion([5,6,7,8])
     |          >>> q1 == q1
     |          >>> q1 == q2
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == q1
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == q2
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) == Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
     |
     |  __imul__(left, right: 'Quaternion') -> 'bool'
     |      Overloaded ``*=`` operator
     |
     |      :return: product
     |      :rtype: Quaternion
     |      :raises: ValueError
     |
     |      ``q1 *= q2`` sets ``q1 := q1 * q2``
     |      ``q1 *= s`` sets ``q1 := q1 * s`` where ``s`` is a scalar
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> q *= Quaternion([5,6,7,8])
     |          >>> print(q)
     |          >>> q *= 2
     |          >>> print(q)
     |
     |      :seealso: :func:`__mul__`
     |
     |  __init__(self, s: 'Any' = None, v=None, check: 'Optional[bool]' = True)
     |      Construct a new quaternion
     |
     |      :param s: scalar part
     |      :type s: float or ndarray(N)
     |      :param v: vector part
     |      :type v: ndarray(3), ndarray(Nx3)
     |
     |      - ``Quaternion()`` constructs a zero quaternion
     |      - ``Quaternion(s, v)`` construct a new quaternion from the scalar ``s``
     |        and the vector ``v``
     |      - ``Quaternion(q)`` construct a new quaternion from the 4-vector
     |        ``q = [s, v]``
     |      - ``Quaternion([q1, q2 .. qN])`` construct a new quaternion with ``N``
     |        values where each element is a 4-vector
     |      - ``Quaternion([Q1, Q2 .. QN])`` construct a new quaternion with ``N``
     |        values where each element is a Quaternion instance
     |      - ``Quaternion(M)`` construct a new quaternion with ``N`` values where
     |        ``Q`` is a 4xN NumPy array.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion()
     |          >>> Quaternion(1, [2,3,4])
     |          >>> Quaternion([1,2,3,4])
     |          >>> q=Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |          >>> len(q)
     |          >>> print(q)
     |
     |  __ipow__(self, n: 'int') -> 'Quaternion'
     |      Overloaded ``=**`` operator
     |
     |      :rtype: Quaternion instance
     |
     |      ``q **= N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
     |      an integer.  If ``N``<0 the result is conjugated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> q **= 2
     |          >>> q
     |          >>> q = Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |          >>> q **= 2
     |          >>> q
     |
     |
     |      :seealso: :func:`__pow__`
     |
     |  __mul__(left, right: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``*`` operator
     |
     |      :return: product
     |      :rtype: Quaternion
     |      :raises: ValueError
     |
     |      - ``q1 * q2`` is the Hamilton product of two quaternions
     |      - ``q * s`` is the scalar product, where ``s`` is a scalar
     |
     |      ==============   ==============   ==============  ================
     |                 Multiplicands                   Product
     |      -------------------------------   --------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ================
     |      Quaternion       Quaternion       Quaternion      Hamilton product
     |      Quaternion       UnitQuaternion   Quaternion      Hamilton product
     |      Quaternion       scalar           Quaternion      scalar product
     |      ==============   ==============   ==============  ================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``prod = left * right``
     |       1      N       N    ``prod[i] = left * right[i]``
     |       N      1       N    ``prod[i] = left[i] * right``
     |       N      N       N    ``prod[i] = left[i] * right[i]``
     |       N      M       -    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])
     |          >>> Quaternion([1,2,3,4]) * 2
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * 2
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * Quaternion([1,2,3,4])
     |          >>> Quaternion([1,2,3,4]) * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |      :seealso: :func:`__rmul__` :func:`__imul__` :func:`~spatialmath.base.quaternions.qqmul`
     |
     |  __ne__(left, right: 'Quaternion') -> 'bool'
     |      Overloaded ``!=`` operator
     |
     |      :rtype: bool
     |
     |      ``q1 != q2`` is True if ``q` is elementwise not equal to ``q2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q1 = Quaternion([1,2,3,4])
     |          >>> q2 = Quaternion([5,6,7,8])
     |          >>> q1 != q1
     |          >>> q1 != q2
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) != q1
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) != q2
     |
     |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
     |
     |  __neg__(self) -> 'Quaternion'
     |      Overloaded unary ``-`` operator
     |
     |      :rtype: Quaternion or UnitQuaternion
     |
     |      ``-q`` is a quaternion with all its components negated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> -Quaternion([1,2,3,4])
     |          >>> -Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  __pow__(self, n: 'int') -> 'Quaternion'
     |      Overloaded ``**`` operator
     |
     |      :rtype: Quaternion instance
     |
     |      ``q ** N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
     |      an integer.  If ``N``<0 the result is conjugated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion([1,2,3,4]) ** 2)
     |          >>> print(Quaternion([1,2,3,4]) ** -1)
     |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) ** 2)
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qpow`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> q
     |
     |  __rmul__(right, left: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``*`` operator
     |
     |      :return: product
     |      :rtype: Quaternion
     |      :raises: ValueError
     |
     |      ``s * q`` is the scalar product, where ``s`` is a scalar.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> 2 * Quaternion([1,2,3,4])
     |          >>> 2 * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |      :seealso: :func:`__mul__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of quaternion
     |
     |      :return: readable representation of quaternion
     |      :rtype: str
     |
     |      Format the quaternion elements into a single line format.  For example::
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> print(x)
     |          >> q = UnitQuaternion.Rx(0.3)
     |
     |      Note that unit quaternions are denoted by different delimiters for
     |      the vector part.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  __sub__(left, right: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``-`` operator
     |
     |      :return: difference
     |      :rtype: Quaternion, UnitQuaternion
     |      :raises: ValueError
     |
     |      ==============   ==============   ==============  ==========================
     |                 Operands                          Difference
     |      -------------------------------   ------------------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ==========================
     |      Quaternion       Quaternion       Quaternion      elementwise sum
     |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
     |      Quaternion       scalar           Quaternion      subtract from each element
     |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
     |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
     |      UnitQuaternion   scalar           Quaternion      subtract from each element
     |      ==============   ==============   ==============  ==========================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``diff = left - right``
     |       1      N       N    ``diff[i] = left - right[i]``
     |       N      1       N    ``diff[i] = left[i] - right``
     |       N      N       N    ``diff[i] = left[i] - right[i]``
     |       N      M       -    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      A scalar of length N is a list, tuple or numpy array.
     |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]) - Quaternion([5,6,7,8])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([1,2,3,4])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  __truediv__(self, other: 'Quaternion')
     |
     |  conj(self) -> 'Quaternion'
     |      Conjugate of quaternion
     |
     |      :rtype: Quaternion instance
     |
     |      ``q.conj()`` is the quaternion ``q`` with the vector part negated, ie.
     |      :math:`q = s \langle -v_x, -v_y, -v_z \rangle`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion.Pure([1,2,3]).conj())
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qconj`
     |
     |  exp(self, tol: 'float' = 20) -> 'Quaternion'
     |      Exponential of quaternion
     |
     |      :param tol: Tolerance when checking for pure quaternion, in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :rtype: Quaternion instance
     |
     |      ``q.exp()`` is the exponential of the quaternion ``q``, ie.
     |
     |      .. math::
     |
     |           e^s \cos \| v \|,  \langle e^s \frac{\vec{v}}{\| \vec{v} \|} \sin \| \vec{v} \| \rangle
     |
     |      For a pure quaternion with vector value :math:`\vec{v}` the the result
     |      is a unit quaternion equivalent to a rotation defined by
     |      :math:`2\vec{v}` intepretted as an Euler vector, that is, parallel to
     |      the axis of rotation and whose norm is the magnitude of rotation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> from math import pi
     |          >>> q = Quaternion([1, 2, 3, 4])
     |          >>> print(q.exp())
     |          >>> q = Quaternion.Pure([pi / 4, 0, 0])
     |          >>> print(q.exp())  # result is a UnitQuaternion
     |          >>> print(q.exp().angvec())
     |
     |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
     |
     |      :seealso: :meth:`Quaternion.log` :meth:`UnitQuaternion.log` :meth:`UnitQuaternion.AngVec` :meth:`UnitQuaternion.EulerVec`
     |
     |  inner(self, other) -> 'float'
     |      Inner product of quaternions
     |
     |      :rtype: float
     |
     |      ``q1.inner(q2)`` is the dot product of the equivalent vectors,
     |      ie. ``numpy.dot(q1.vec, q2.vec)``.
     |      The value of ``q.inner(q)`` is the same as ``q.norm ** 2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).inner(Quaternion([5,6,7,8]))
     |          >>> numpy.dot([1,2,3,4], [5,6,7,8])
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qinner`
     |
     |  log(self) -> 'Quaternion'
     |      Logarithm of quaternion
     |
     |      :rtype: Quaternion instance
     |
     |      ``q.log()`` is the logarithm of the quaternion ``q``, ie.
     |
     |      .. math::
     |
     |           \ln \| q \|,  \langle \frac{\vec{v}}{\| \vec{v} \|} \cos^{-1} \frac{s}{\| q \|} \rangle
     |
     |      For a ``UnitQuaternion`` the logarithm is a pure quaternion whose vector
     |      part :math:`\vec{v}` and :math:`\vec{v}/2` is a Euler vector: parallel
     |      to the axis of rotation and whose norm is the magnitude of rotation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion, UnitQuaternion
     |          >>> from math import pi
     |          >>> q = Quaternion([1, 2, 3, 4])
     |          >>> print(q.log())
     |          >>> q = UnitQuaternion.Rx(pi / 2)
     |          >>> print(q.log())
     |
     |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
     |
     |      :seealso: :meth:`Quaternion.exp` :meth:`Quaternion.log` :meth:`UnitQuaternion.angvec`
     |
     |  norm(self) -> 'float'
     |      Norm of quaternion
     |
     |      :rtype: float
     |
     |      ``q.norm()`` is the norm or length of the quaternion
     |      :math:`\sqrt{s^2 + v_x^2 + v_y^2 + v_z^2}`
     |
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).norm()
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).norm()
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  unit(self) -> 'UnitQuaternion'
     |      Unit quaternion
     |
     |      :rtype: UnitQuaternion instance
     |
     |      ``q.unit()`` is the quaternion ``q`` normalized to have a unit length.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> print(q)
     |          >>> print(q.unit())
     |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).unit())
     |
     |      Note that the return type is different, a ``UnitQuaternion``, which is
     |      distinguished by the use of double angle brackets to delimit the
     |      vector part.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  Pure(v: 'ArrayLike3') -> 'Quaternion'
     |      Construct a pure quaternion from a vector
     |
     |      :param v: vector
     |      :type v: 3-element array_like
     |
     |      ``Quaternion.Pure(v)`` is a Quaternion with a zero scalar part and the
     |      vector part set to ``v``,
     |      ie. :math:`q = 0 \langle v_x, v_y, v_z \rangle`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion.Pure([1,2,3]))
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x: 'ArrayLike4') -> 'bool'
     |      Test if vector is valid quaternion
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: explicitly check vector is unit length [default True]
     |      :type check: bool
     |      :return: True if the matrix has shape (4,).
     |      :rtype: bool
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> import numpy as np
     |          >>> Quaternion.isvalid(np.r_[1, 0, 0, 0])
     |          >>> Quaternion.isvalid(np.r_[1, 2, 3, 4])
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  matrix
     |      Matrix equivalent of quaternion
     |
     |      :rtype: Numpy array, shape=(4,4)
     |
     |      ``q.matrix`` is a 4x4 matrix which encodes the arithmetic rules of Hamilton multiplication.
     |      This matrix, multiplied by the 4-vector equivalent of a second quaternion, results in the 4-vector
     |      equivalent of the Hamilton product.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).matrix
     |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])   # Hamilton product
     |          >>> Quaternion([1,2,3,4]).matrix @ Quaternion([5,6,7,8]).vec  # matrix-vector product
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qmatrix`
     |
     |  s
     |      Scalar part of quaternion
     |
     |      :return: scalar part of quaternion
     |      :rtype: float or numpy.ndarray
     |
     |      ``q.s`` is the scalar part.  If `len(q)` is:
     |
     |          - 1, return a scalar float
     |          - N>1, return a NumPy array shape=(N,) is returned.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).s
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).s
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (4,)
     |      :rtype: tuple
     |
     |  v
     |      Vector part of quaternion
     |
     |      :return: vector part of quaternion
     |      :rtype: NumPy ndarray
     |
     |      ``q.v`` is the vector part.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(3,)
     |          - N>1, return a NumPy array shape=(N,3).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).v
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).v
     |
     |  vec
     |      Quaternion as a vector
     |
     |      :return: quaternion expressed as a 4-vector
     |      :rtype: numpy ndarray, shape=(4,)
     |
     |      ``q.vec`` is the quaternion as a vector.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(4,)
     |          - N>1, return a NumPy array shape=(N,4).
     |
     |      The quaternion coefficients are in the order (s, vx, vy, vz), ie. with
     |      the scalar (real part) first.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).vec
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec
     |
     |  vec_xyzs
     |      Quaternion as a vector
     |
     |      :return: quaternion expressed as a 4-vector
     |      :rtype: numpy ndarray, shape=(4,)
     |
     |      ``q.vec_xyzs`` is the quaternion as a vector.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(4,)
     |          - N>1, return a NumPy array shape=(N,4).
     |
     |      The quaternion coefficients are in the order (vx, vy, vz, s), ie. with
     |      the scalar (real part) last. This is useful when exporting to other
     |      packages like three.js or pybullet.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).vec_xyzs
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec_xyzs
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class UnitQuaternion(Quaternion)
     |  UnitQuaternion(s: 'Any' = None, v=None, norm: 'Optional[bool]' = True, check: 'Optional[bool]' = True)
     |
     |  Unit quaternion class
     |
     |  A unit quaternion can be considered an ordered pair :math:`(s, \vec{v})`
     |  where :math:`s \in \mathbb{R}` is the *scalar* part and :math:`\vec{v} = (v_x, v_y, v_z) \in \mathbb{R}^3`
     |  is the *vector* part and is often written as
     |
     |  .. math:: \q = s \langle v_x, v_y, v_z \rangle
     |
     |  and subject to a unit-length constraint :math:`s^2+v_x^2+v_y^2+v_z^2 = 1`.
     |
     |  A unit-quaternion can be considered as a rotation :math:`\theta` about the
     |  vector :math:`\vec{v}`, so the unit quaternion can also be
     |  written as
     |
     |  .. math:: \q = \cos \frac{\theta}{2} \sin \frac{\theta}{2} <v_x v_y v_z>
     |
     |  The quaternion :math:`\q` and :math:`-\q` represent the equivalent rotation, and this is referred to
     |  as a double mapping.
     |
     |  .. inheritance-diagram:: spatialmath.quaternion.UnitQuaternion
     |      :top-classes: collections.UserList
     |      :parts: 1
     |
     |  The ``UnitQuaternion`` class inherits many methods from the ``Quaternion`` class
     |
     |  Method resolution order:
     |      UnitQuaternion
     |      Quaternion
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  SE3(self) -> 'SE3'
     |      Unit quaternion as SE3 instance
     |
     |      :return: an SE(3) representation
     |      :rtype: SE3 instance
     |
     |      ``q.SE3()`` is an ``SE3`` instance representing the same rotation
     |      as the unit quaternion ``q`` and with zero translation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> UQ.Rz(0.3).SE3()
     |
     |  SO3(self) -> 'SO3'
     |      Unit quaternion as SO3 instance
     |
     |      :return: an SO(3) representation
     |      :rtype: SO3 instance
     |
     |      ``q.SO3()`` is an ``SO3`` instance representing the same rotation
     |      as the unit quaternion ``q``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> UQ.Rz(0.3).SO3()
     |
     |  __eq__(left, right: 'UnitQuaternion') -> 'bool'
     |      Overloaded ``==`` operator
     |
     |      :rtype: bool
     |
     |      ``q1 == q2`` is True if ``q1`` is elementwise equal to ``q2`` and accounts for the
     |      double mapping. Supports broadcasting.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q1 = UQ.Rx(0.3)
     |          >>> q2 = UQ.Ry(0.3)
     |          >>> q1 == q1
     |          >>> q1 == (-q1)
     |          >>> q1 == q2
     |          >>> UQ([q1, q2]) == q1
     |          >>> UQ([q1, q2]) == q2
     |          >>> UQ([q1, q2]) == UQ([q1, q2])
     |
     |      :seealso: :func:`__ne__` :func:`~spatialmath.base.quaternions.qisequal`
     |
     |  __imul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
     |      Multiply unit quaternion in place
     |
     |      :return: product
     |      :rtype: UnitQuaternion, Quaternion
     |      :raises: ValueError
     |
     |      Multiplies a quaternion in place. If the right operand is a list,
     |      the result will be a list.
     |
     |      Example::
     |
     |          >>> q = UQ.Rx(0.3)
     |          >>> q *= UQ.Rx(0.3)
     |          >>> q
     |
     |      :seealso: :func:`__mul__`
     |
     |  __init__(self, s: 'Any' = None, v=None, norm: 'Optional[bool]' = True, check: 'Optional[bool]' = True)
     |      Construct a UnitQuaternion instance
     |
     |      :param norm: explicitly normalize the quaternion [default True]
     |      :type norm: bool
     |      :param check: explicitly check validity of argument [default True]
     |      :type check: bool
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |      :raises: ValueError
     |
     |      - ``UnitQuaternion()`` constructs the identity quaternion 1<0,0,0>
     |      - ``UnitQuaternion(s, v)`` constructs a unit quaternion with specified
     |        real ``s`` and ``v`` vector parts. ``v`` is a 3-vector given as a
     |        list, tuple, or ndarray(3). If ``norm`` is True the resulting
     |        quaternion is normalized.
     |      - ``UnitQuaternion(v)`` constructs a unit quaternion with specified
     |        elements from ``v`` which is a 4-vector given as a list, tuple, or ndarray(4). Also known
     |        as the Euler parameters.
     |      - ``UnitQuaternion(M)`` construct a new unit quaternion with ``N`` values where ``Q`` is a Nx4 NumPy array
     |        whose rows are the quaternion in vector form
     |      - ``UnitQuaternion(R)`` constructs a unit quaternion from an SO(3)
     |        rotation matrix given as a ndarray(3,3). If ``check`` is True
     |        test the rotation submatrix for orthogonality.
     |      - ``UnitQuaternion(X)`` constructs a unit quaternion from the rotational
     |        part of ``X`` which is an SO3 or SE3 instance.  If len(X) > 1 then
     |        the resulting unit quaternion is of the same length.
     |      - ``UnitQuaternion([q1, q2 .. qN])`` construct a new unit quaternion with ``N`` values where each element is a 4-vector
     |      - ``UnitQuaternion([Q1, Q2 .. QN])`` construct a new unit quaternion with ``N`` values where each element is a UnitQuaternion instance
     |      - ``UnitQuaternion([X1, X2 .. XN])`` construct a new unit quaternion with ``N`` values where each element is an SO3 or SE3 instance
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q = UQ()
     |          >>> q         # repr()
     |          >>> print(q)  # str()
     |
     |  __matmul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
     |      Overloaded @ operator
     |
     |      :return: product :rtype: UnitQuaternion
     |
     |      - ``q1 @ q2`` is the Hamilton product of ``q1`` and ``q2``, both unit
     |        quaternions, followed by explicit normalization.
     |
     |      - `` q1 @= q2`` as above.
     |
     |      .. note:: This operator is functionally equivalent to ``*`` but is more
     |          costly.  It is useful for cases where a pose is incrementally update
     |          over many cycles.
     |
     |  __mul__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
     |      Multiply unit quaternion
     |
     |      :return: product
     |      :rtype: Quaternion, UnitQuaternion
     |      :raises: ValueError
     |
     |      ==============   ==============   ==============  ================
     |                 Multiplicands                   Product
     |      -------------------------------   --------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ================
     |      UnitQuaternion   Quaternion       Quaternion      Hamilton product
     |      UnitQuaternion   UnitQuaternion   UnitQuaternion  Hamilton product
     |      UnitQuaternion   scalar           Quaternion      scalar product
     |      UnitQuaternion   3-vector         3-vector        vector rotation
     |      UnitQuaternion   3xN array        3xN array       vector rotations
     |      ==============   ==============   ==============  ================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rx(0.3) * UQ.Rx(0.4))
     |          >>> print(UQ.Rx(0.3) * 2)
     |          >>> print(UQ.Rx(0.3) * [1, 2, 3])
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``prod = left * right``
     |       1      N       N    ``prod[i] = left * right[i]``
     |       N      1       N    ``prod[i] = left[i] * right``
     |       N      N       N    ``prod[i] = left[i] * right[i]``
     |       N      M       n/a    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      A scalar of length N is a list, tuple or numpy array.
     |      A 3-vector of length N is a 3xN numpy array, where each column is
     |      a 3-vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rx(0.3) * UQ.Rx(0.4))
     |          >>> q = UQ.Rx(0.3)
     |          >>> q *= UQ.Rx(0.4))
     |          >>> print(q)
     |          >>> print(UQ.Rx(0.3) * UQ.Rx([0.4, 0.6]))
     |          >>> print(UQ.Rx([0.3, 0.6]) * UQ.Rx(0.3))
     |          >>> print(UQ.Rx([0.3, 0.6]) * UQ.Rx([0.3, 0.6]))
     |
     |      :seealso: :meth:`Quaternion.__mul__`
     |
     |  __ne__(left, right: 'UnitQuaternion') -> 'bool'
     |      Overloaded ``!=`` operator
     |
     |      :rtype: bool
     |
     |      ``q1 != q2`` is True if ``q1`` is elementwise not equal to ``q2`` and accounts for the
     |      double mapping. Supports broadcasting.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q1 = UQ.Rx(0.3)
     |          >>> q2 = UQ.Ry(0.3)
     |          >>> q1 != q1
     |          >>> q1 != (-q1)
     |          >>> q1 != q2
     |          >>> UQ([q1, q2]) == q1
     |          >>> UQ([q1, q2]) == q2
     |          >>> UQ([q1, q2]) == UQ([q1, q2])
     |
     |      :seealso: :func:`__eq__` :func:`~spatialmath.base.quaternions.qisequal`
     |
     |  __truediv__(left, right: 'UnitQuaternion') -> 'UnitQuaternion'
     |      Overloaded ``/`` operator
     |
     |      :rtype: Quaternion or UnitQuaternion
     |
     |      - ``q1 / q2`` is equivalent to ``q1 * q1.inv()``.
     |      - ``q / s`` performs elementwise division of the elements of ``q`` by
     |        ``s``. This is not a group operation so the result will be a
     |        Quaternion.
     |
     |      ==============   ==============   ==============  ===========================
     |                 Multiplicands                   Quotient
     |      -------------------------------   -------------------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ===========================
     |      UnitQuaternion   UnitQuaternion   UnitQuaternion  Hamilton product by inverse
     |      UnitQuaternion   scalar           Quaternion      element-wise division
     |      ==============   ==============   ==============  ===========================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rx(0.3) / UQ.Rx(0.3))
     |          >>> print(UQ.Rx(0.3) / 2)
     |
     |      For pose composition either or both operands may hold more than one value which
     |      results in the composition holding more than one value according to:
     |
     |      =========   ==========   ====  =====================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  =====================================
     |       1          1             1    ``quo = left * right.inv()``
     |       1          M             M    ``quo[i] = left * right[i].inv()``
     |       N          1             M    ``quo[i] = left[i] * right.inv()``
     |       M          M             M    ``quo[i] = left[i] * right[i].inv()``
     |      =========   ==========   ====  =====================================
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rx(0.3) / UQ.Rx(0.3))
     |          >>> print(UQ.Rx([0.3, 0.6]) / UQ.Rx(0.3))
     |          >>> print(UQ.Rx(0.3) / UQ.Rx([0.3, 0.6]))
     |          >>> print(UQ.Rx([0.3, 0.6]) / UQ.Rx([0.3, 0.6]))
     |
     |  angdist(self, other: 'UnitQuaternion', metric: 'Optional[int]' = 3) -> 'float'
     |      Angular distance metric between unit quaternions
     |
     |      :param other: second unit quaternion
     |      :type other: UnitQuaternion instance
     |      :param metric: metric, default is 3
     |      :type metric: int
     |      :raises TypeError: if other is not a UnitQuaternion
     |      :return: angle in radians
     |      :rtype: float
     |
     |      ``q1.angdist(q2)`` is the geodesic norm, or geodesic distance between two
     |      unit quaternions.  We can consider it as the angle between two quaternions.
     |
     |      Several metrics are supported:
     |
     |      ======   ===============================================================
     |      Metric   Details
     |      ======   ===============================================================
     |      0        :math:`1 - | \q_1 \bullet \q_2 | \in [0, 1]`
     |      1        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      2        :math:`\cos^{-1} | \q_1 \bullet \q_2 | \in [0, \pi/2]`
     |      3        :math:`2 \tan^{-1} \| \q_1 \pm \q_2\| / \|\q_1 \mp \q_2\| \in [0, \pi/2]`
     |      4        :math:`\cos^{-1} \left( 2 (\q_1 \bullet \q_2)^2 - 1\right) \in [0, 1]`
     |      ======   ===============================================================
     |
     |      Metric 3 computes the sum and difference of the quaternions and uses
     |      the largest value in the denominator.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion
     |          >>> q1 = UnitQuaternion.Rx(0.3)
     |          >>> q2 = UnitQuaternion.Ry(0.3)
     |          >>> print(q1.angdist(q1))
     |          >>> print(q1.angdist(q2))
     |
     |      .. note::
     |          - metrics 1, 2, 4 can throw ValueError "math domain error" due to
     |            numeric errors which push the argument of ``acos()`` marginally
     |            outside its domain [0, 1].
     |          - metrics 2 and 3 are equivalent, but 3 is more robust
     |          - SMTB-MATLAB uses metric 3 for UnitQuaternion.angle()
     |          - MATLAB's quaternion.dist() uses metric 4
     |
     |  angvec(self, unit: 'Optional[str]' = 'rad') -> 'Tuple[float, R3]'
     |      Unit quaternion as angle and rotation vector
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param check: check that rotation matrix is valid
     |      :type check: bool
     |      :return: :math:`(\theta, {\bf v})`
     |      :rtype: float, ndarray(3)
     |
     |      ``q.angvec()`` is a tuple :math:`(\theta, v)` containing the rotation
     |      angle and a rotation axis which is equivalent to the rotation of
     |      the unit quaternion ``q``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> UQ.Rz(0.3).angvec()
     |
     |      :seealso: :meth:`Quaternion.AngVec` :meth:`UnitQuaternion.log` :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  animate(self, *args: 'List', **kwargs)
     |      Plot unit quaternion as an animated coordinate frame
     |
     |      :param start: initial pose, defaults to null/identity
     |      :type start: UnitQuaternion
     |      :param `**kwargs`: plotting options
     |
     |      - ``q.animate()`` displays the orientation ``q`` as a coordinate frame moving
     |        from the origin in either 3D.  There are
     |        many options, see the links below.
     |      - ``q.animate(*args, start=q1)`` displays the orientation ``q`` as a coordinate
     |        frame moving from orientation ``q11``, in 3D.  There are
     |        many options, see the links below.
     |
     |      Example::
     |
     |          >>> X = UQ.Rx(0.3)
     |          >>> X.animate(frame='A', color='green')
     |          >>> X.animate(start=UQ.Ry(0.2))
     |
     |      :see :func:`~spatialmath.base.transforms3d.tranimate` :func:`~spatialmath.base.transforms3d.trplot`
     |
     |  dot(self, omega: 'ArrayLike3') -> 'R4'
     |      Rate of change of a unit quaternion in world frame
     |
     |      :param ω: angular velocity in world frame
     |      :type ω: 3-element array_like
     |      :return: rate of change of unit quaternion
     |      :rtype: ndarray(4)
     |
     |      ``q.dot(ω)`` is the rate of change of the elements of the unit quaternion ``q``
     |      which represents the orientation of a body frame with angular velocity ``ω`` in
     |      the world frame.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qdot`
     |
     |  dotb(self, omega: 'ArrayLike3') -> 'R4'
     |      Rate of change of a unit quaternion in body frame
     |
     |      :param ω: angular velocity in body frame
     |      :type ω: 3-element array_like
     |      :return: rate of change of unit quaternion
     |      :rtype: ndarray(4)
     |
     |      ``q.dotb(ω)`` is the rate of change of the elements of the unit quaternion ``q``
     |      which represents the orientation of a body frame with angular velocity ``ω`` in
     |      the body frame.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qdotb`
     |
     |  eul(self, unit: 'Optional[str]' = 'rad') -> 'Union[R3, RNx3]'
     |      Unit quaternion as Euler angles
     |
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of Euler angles
     |      :rtype: ndarray(3)
     |
     |      ``q.eul`` is the Euler angle representation of the rotation.  Euler angles are
     |      a 3-vector :math:`(\phi, \theta, \psi)` which correspond to consecutive
     |      rotations about the Z, Y, Z axes respectively.
     |
     |      If ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(N,3)
     |
     |      - ndarray with shape=(3,), if len(R) == 1
     |      - ndarray with shape=(N,3), if len(R) = N > 1
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> UQ.Rz(0.3).eul()
     |          >>> UQ.Ry([0.3, 0.4]).eul()
     |
     |      :seealso: :meth:`SE3.Eul` :func:`~spatialmath.base.transforms3d.tr2eul`
     |
     |  increment(self, w: 'ArrayLike3', normalize: 'Optional[bool]' = False) -> 'None'
     |      Quaternion incremental update
     |
     |      :param w: angular displacement, Euler vector
     |      :type w: array_like(3)
     |      :param normalize: normalize the result, defaults to False
     |      :type normalize: bool, optional
     |
     |      .. note:: The object state is updated
     |
     |  interp(self, end: 'UnitQuaternion', s: 'float' = 0, shortest: 'Optional[bool]' = False) -> 'UnitQuaternion'
     |      Interpolate between two unit quaternions
     |
     |      :param end: final unit quaternion
     |      :type end: UnitQuaternion
     |      :param shortest: Take the shortest path along the great circle
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :return: interpolated unit quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``q0.interp(q1, s)`` is a unit quaternion that is interpolated between
     |        ``q0`` when s=0 and ``q1`` when s=1. Spherical linear interpolation
     |        (slerp) is used.  If ``s`` is an ndarray(n) then the result will be
     |        a UnitQuaternion with n values.
     |
     |      - ``q0.interp(q1, N)`` interpolate between ``q0`` and ``q1`` in ``N``
     |        steps.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q1 = UQ.Rx(0.3); q2 = UQ.Rz(-0.4)
     |          >>> print(q1)
     |          >>> print(q2)
     |          >>> q1.interp(q2, 0)    # this is q1
     |          >>> q1.interp(q2, 1,)   # this is q2
     |          >>> q1.interp(q2, 0.5)  # this is in between
     |          >>> q = q1.interp(q2, 11)  # in 11 steps
     |          >>> len(q)
     |          >>> q[0]                # this is q1
     |          >>> q[5]                # this is in between
     |
     |      .. note:: values of ``s`` are silently clipped to the range [0, 1]
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qslerp`
     |
     |  interp1(self, s: 'float' = 0, shortest: 'Optional[bool]' = False) -> 'UnitQuaternion'
     |      Interpolate a unit quaternion
     |
     |      :param shortest: Take the shortest path along the great circle
     |      :param s: interpolation coefficient, range 0 to 1, or number of steps
     |      :type s: array_like or int
     |      :return: interpolated unit quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``q.interp1(s)`` is a unit quaternion that is interpolated between
     |        identity when s=0 and ``q`` when s=1. Spherical linear interpolation
     |        (slerp) is used.  If ``s`` is an ndarray(n) then the result will be
     |        a UnitQuaternion with n values.
     |
     |      - ``q.interp1(N)`` interpolate between identity and ``q1`` in ``N``
     |        steps.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q = UQ.Rx(0.3)
     |          >>> print(q)
     |          >>> q.interp1(0)    # this is identity
     |          >>> q.interp1(1)    # this is q
     |          >>> q.interp1(0.5)  # this is in between
     |          >>> qi = q.interp1(11)  # in 11 steps
     |          >>> len(qi)
     |          >>> qi[0]                # this is q1
     |          >>> qi[5]                # this is in between
     |
     |      .. note:: values of ``s`` are silently clipped to the range [0, 1]
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qslerp`
     |
     |  inv(self) -> 'UnitQuaternion'
     |      Inverse of unit quaternion
     |
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      ``q.inv()`` is the inverse of the unit-quaternion.  This is a group operation
     |      and the product of the unit-quaternion and its inverse is the identity quaternion.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion
     |          >>> print(UQ.Rx(0.3).inv())
     |          >>> print(UQ.Rx(0.3).inv() * UQ.Rx(0.3))
     |          >>> print(UQ.Rx([0.3, 0.6]).inv())
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qinv`
     |
     |  plot(self, *args: 'List', **kwargs)
     |      Plot unit quaternion as a coordinate frame
     |
     |      :param `**kwargs`: plotting options
     |
     |      - ``q.plot()`` displays the orientation ``q`` as a coordinate frame in 3D.
     |        There are many options, see the links below.
     |
     |      Example::
     |
     |          >>> q = UQ.Rx(0.3)
     |          >>> q.plot(frame='A', color='green')
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.trplot`
     |
     |  rpy(self, unit: 'Optional[str]' = 'rad', order: 'Optional[str]' = 'zyx') -> 'Union[R3, RNx3]'
     |      Unit quaternion as roll-pitch-yaw angles
     |
     |      :param order: angle sequence order, default to 'zyx'
     |      :type order: str
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3-vector of roll-pitch-yaw angles
     |      :rtype: ndarray(3) or ndarray(n,3)
     |
     |      ``q.rpy`` is the roll-pitch-yaw angle representation of the 3D rotation.  The angles are
     |      a 3-vector :math:`(r, p, y)` which correspond to successive rotations about the axes
     |      specified by ``order``:
     |
     |          - 'zyx' [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  Convention for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - 'xyz', rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. Convention for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - 'yxz', rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. Convention for a camera with z-axis parallel
     |            to the optic axis and x-axis parallel to the pixel rows.
     |
     |      If ``len(x)`` is:
     |
     |      - 1, return an ndarray with shape=(3,)
     |      - N>1, return ndarray with shape=(N,3)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> UQ.Rx(0.3).rpy()
     |          >>> UQ.Rz([0.2, 0.3]).rpy()
     |
     |      :seealso: :meth:`SE3.RPY` :func:`~spatialmath.base.transforms3d.tr2rpy`
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  AngVec(theta: 'float', v: 'ArrayLike3', *, unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from rotation angle and axis
     |
     |      :param theta: rotation
     |      :type theta: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param v: rotation axis, 3-vector
     |      :type v: array_like
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      ``UnitQuaternion.AngVec(θ, v)`` is a unit quaternion that describes the 3D rotation
     |      defined by a rotation of ``θ`` about the 3-vector ``v``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.AngVec(0, [1,0,0]))
     |          >>> print(UQ.AngVec(90, [1,0,0], unit='deg'))
     |
     |      .. note:: :math:`\theta = 0` the result in an identity quaternion, otherwise
     |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
     |
     |      :seealso: :meth:`UnitQuaternion.angvec` :meth:`UnitQuaternion.exp` :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  Eul(*angles: 'List[float]', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from Euler angles
     |
     |      :param 𝚪: 3-vector of Euler angles
     |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion.Eul(𝚪)`` is a unit quaternion that describes the 3D
     |        rotation defined by a 3-vector of Euler angles :math:`\Gamma = (\phi,
     |        \theta, \psi)` which correspond to consecutive rotations about the Z,
     |        Y, Z axes respectively.
     |
     |      - ``UnitQuaternion.Eul(φ, θ, ψ)`` as above but the angles are provided
     |        as three scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Eul([0.1, 0.2, 0.3]))
     |
     |      :seealso: :meth:`UnitQuaternion.RPY` :meth:`SE3.eul` :meth:`SE3.Eul` :meth:`~spatialmath.base.transforms3d.eul2r`
     |
     |  EulerVec(w: 'ArrayLike3') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from an Euler rotation vector
     |
     |      :param ω: rotation axis
     |      :type ω: 3-element array_like
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      ``UnitQuaternion.EulerVec(ω)`` is a unit quaternion that describes the 3D rotation
     |      defined by a rotation of :math:`\theta = \lVert \omega \rVert` about the
     |      unit 3-vector :math:`\omega / \lVert \omega \rVert`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.EulerVec([0.5,0,0]))
     |
     |      .. note:: :math:`\theta \eq 0` the result in an identity matrix, otherwise
     |          ``V`` must have a finite length, ie. :math:`|V| > 0`.
     |
     |      :seealso: :meth:`SE3.angvec` :func:`~spatialmath.base.transforms3d.angvec2r`
     |
     |  OA(o: 'ArrayLike3', a: 'ArrayLike3') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from two vectors
     |
     |      :param o: 3-vector parallel to Y- axis
     |      :type o: array_like
     |      :param a: 3-vector parallel to the Z-axis
     |      :type a: array_like
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      ``UnitQuaternion.OA(O, A)`` is a unit quaternion that describes the 3D rotation defined in terms of
     |      vectors parallel to the Y- and Z-axes of its reference frame.  In robotics these axes are
     |      respectively called the orientation and approach vectors defined such that
     |      R = [N O A] and N = O x A.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.OA([0,0,-1], [0,1,0]))
     |
     |      .. note::
     |
     |          - Only the ``A`` vector is guaranteed to have the same direction in the resulting
     |          rotation matrix
     |          - ``O`` and ``A`` do not have to be unit-length, they are normalized
     |          - ``O`` and ``A` do not have to be orthogonal, so long as they are not parallel
     |
     |      :seealso: :func:`~spatialmath.base.transforms3d.oa2r`
     |
     |  RPY(*angles, order: 'Optional[str]' = 'zyx', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from roll-pitch-yaw angles
     |
     |      :param 𝚪: 3-vector of roll-pitch-yaw angles
     |      :type 𝚪: 3 floats, array_like(3) or ndarray(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param unit: rotation order: 'zyx' [default], 'xyz', or 'yxz'
     |      :type unit: str
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion.RPY(𝚪)`` is a unit quaternion that describes the 3D
     |        rotation defined by a  3-vector of roll, pitch, yaw angles
     |        :math:`\Gamma = (r, p, y)` which correspond to successive rotations
     |        about the axes specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch
     |            about the new y-axis, then by roll about the new x-axis.
     |            Convention for a mobile robot with x-axis forward and y-axis
     |            sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the
     |            new y-axis, then by roll about the new z-axis. Convention for a
     |            robot gripper with z-axis forward and y-axis between the gripper
     |            fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the
     |            new x-axis, then by roll about the new z-axis. Convention for a
     |            camera with z-axis parallel to the optic axis and x-axis parallel
     |            to the pixel rows.
     |
     |
     |      - ``UnitQuaternion.RPY(⍺, β, 𝛾)`` as above but the angles are provided
     |        as three scalars.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.RPY([0.1, 0.2, 0.3]))
     |
     |      :seealso: :meth:`UnitQuaternion.Eul` :meth:`SE3.rpy` :meth:`SE3.RPY` :func:`~spatialmath.base.transforms3d.rpy2r`
     |
     |  Rand(N: 'int' = 1, *, theta_range: 'Optional[ArrayLike2]' = None, unit: 'str' = 'rad') -> 'UnitQuaternion'
     |      Construct a new random unit quaternion
     |
     |      :param N: number of random rotations
     |      :type N: int
     |      :param theta_range: angular magnitude range [min,max], defaults to None -> [0,pi].
     |      :type xrange: 2-element sequence, optional
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: random unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion.Rand()`` is a uniformly distributed random unit quaternion value.
     |      - ``SO3.Rand(N)`` is a unit quaternion instance containing a sequence of N random unit quaternion
     |        values.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rand())
     |          >>> print(UQ.Rand(3))
     |
     |      :seealso: :meth:`UnitQuaternion.Rand`
     |
     |  Rx(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a UnitQuaternion object representing rotation about the X-axis
     |
     |      :arg θ: rotation angle
     |      :type θ: array_like
     |      :arg unit: rotation unit 'rad' [default] or 'deg'
     |      :type unit: str
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
     |        rotation of ``θ`` radians about the X-axis.
     |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
     |        rotation of ``θ`` degrees about the X-axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rx(0.3))
     |          >>> print(UQ.Rx([0, 0.3, 0.6]))
     |
     |  Ry(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a UnitQuaternion object representing rotation about the Y-axis
     |
     |      :arg θ: rotation angle
     |      :type θ: array_like
     |      :arg unit: rotation unit 'rad' [default] or 'deg'
     |      :type unit: str
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
     |        rotation of ``θ`` radians about the Y-axis.
     |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
     |        rotation of ``θ`` degrees about the Y-axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Ry(0.3))
     |          >>> print(UQ.Ry([0, 0.3, 0.6]))
     |
     |  Rz(angles: 'ArrayLike', unit: 'Optional[str]' = 'rad') -> 'UnitQuaternion'
     |      Construct a UnitQuaternion object representing rotation about the Z-axis
     |
     |      :arg θ: rotation angle
     |      :type θ: array_like
     |      :arg unit: rotation unit 'rad' [default] or 'deg'
     |      :type unit: str
     |      :return: unit-quaternion
     |      :rtype: UnitQuaternion instance
     |
     |      - ``UnitQuaternion(θ)`` constructs a unit quaternion representing a
     |        rotation of ``θ`` radians about the Z-axis.
     |      - ``UnitQuaternion(θ, 'deg')`` constructs a unit quaternion representing a
     |        rotation of ``θ`` degrees about the Z-axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> print(UQ.Rz(0.3))
     |          >>> print(UQ.Rz([0, 0.3, 0.6]))
     |
     |  Vec3(vec: 'ArrayLike3') -> 'UnitQuaternion'
     |      Construct a new unit quaternion from its vector part
     |
     |      :param vec: vector part of unit quaternion
     |      :type vec: 3-element array_like
     |
     |      ``UnitQuaternion.Vec(v)`` is a new unit quaternion with the specified vector part
     |      and the scalar part is
     |
     |      .. math:: s = \sqrt{1 - v_x^2 - v_y^2 - v_z^2}
     |
     |      The unit quaternion will always have a positive scalar part.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q = UQ.Rz(-4)
     |          >>> print(q)
     |          >>> q.vec3
     |          >>> q2 = UQ.Vec3(q.vec3)
     |          >>> print(q2)
     |          >>> q == q2
     |
     |      :seealso: :meth:`UnitQuaternion.vec3`
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(x: 'ArrayLike', check: 'Optional[bool]' = True) -> 'bool'
     |      Test if vector is valid unit quaternion
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: explicitly check vector is unit length [default True]
     |      :type check: bool
     |      :return: True if the matrix has shape (4,).
     |      :rtype: bool
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion
     |          >>> import numpy as np
     |          >>> UnitQuaternion.isvalid(np.r_[1, 0, 0, 0])
     |          >>> UnitQuaternion.isvalid(np.r_[1, 2, 3, 4])
     |
     |  qvmul(qv1: 'ArrayLike3', qv2: 'ArrayLike3') -> 'R3'
     |      Multiply unit quaternions defined by unique vector parts
     |
     |      :param qv1: vector representation of first multiplicand
     |      :type qv1: ndarray(3)
     |      :param qv1: vector representation of second multiplicand
     |      :type qv1: ndarray(3)
     |
     |      ``UnitQuaternion(qv1, qv2)`` is the Hamilton product of two unit quaternions
     |      represented in minimal vector form.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q1 = UQ.Rx(0.3)
     |          >>> q2 = UQ.Ry(-0.3)
     |          >>> qv1 = q1.vec3
     |          >>> qv1
     |          >>> qv2 = q2.vec3
     |          >>> qv = UQ.qvmul(qv1, qv2)
     |          >>> qv
     |          >>> print(UQ.Vec3(qv))
     |          >>> print(UQ.Rx(0.3) * UQ.Ry(-0.3))
     |
     |      :seealso: :meth:`UnitQuaternion.vec3` :meth:`UnitQuaternion.Vec3`
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  R
     |      Unit quaternion as a rotation matrix
     |
     |      :return: equivalent rotational matrix
     |      :rtype: ndarray(3,3)
     |
     |      ``q.R`` returns the rotation matrix which describes the equivalent rotation. If ``len(x)`` is:
     |
     |          - 1, return an ndarray with shape=(3,3)
     |          - N>1, return ndarray with shape=(N,3,3)
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q = UQ.Rx(0.3)
     |          >>> q.R
     |          >>> q = UQ.Rx([0.3, 0.4])
     |          >>> q.R
     |
     |      .. warning:: The i'th rotation matrix is ``x[i,:,:]`` or simply
     |          ``x[i]``. This is different to the MATLAB version where the i'th
     |          rotation matrix is ``x(:,:,i)``.
     |
     |  vec3
     |      Unit quaternion unique vector part
     |
     |      :return: vector part of unit quaternion
     |      :rtype: numpy array, shape=(3,)
     |
     |      ``q.vec3`` is the vector part of a unit quaternion.  If ``q`` has a negative scalar
     |      part we take the vector part of ``-q``, since  ``q`` and ``-q`` represent the
     |      same rotation.
     |
     |      This vector part is a minimal unique representation of the unit quaternion and can be used in
     |      optimization procedures such as bundle adjustment.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import UnitQuaternion as UQ
     |          >>> q = UQ.Rz(-4)
     |          >>> print(q)
     |          >>> q.vec3
     |          >>> q2 = UQ.Vec3(q.vec3)
     |          >>> print(q2)
     |          >>> q == q2
     |
     |      :seealso: :meth:`UnitQuaternion.Vec3`
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from Quaternion:
     |
     |  __add__(left, right: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``+`` operator
     |
     |      :return: sum
     |      :rtype: Quaternion, UnitQuaternion
     |      :raises: ValueError
     |
     |      ==============   ==============   ==============  ===================
     |                 Operands                            Sum
     |      -------------------------------   -----------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ===================
     |      Quaternion       Quaternion       Quaternion      elementwise sum
     |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
     |      Quaternion       scalar           Quaternion      add to each element
     |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
     |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
     |      UnitQuaternion   scalar           Quaternion      add to each element
     |      ==============   ==============   ==============  ===================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``sum = left + right``
     |       1      N       N    ``sum[i] = left + right[i]``
     |       N      1       N    ``sum[i] = left[i] + right``
     |       N      N       N    ``sum[i] = left[i] + right[i]``
     |       N      M       -    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      A scalar of length N is a list, tuple or numpy array.
     |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]) + Quaternion([5,6,7,8])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([1,2,3,4])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) + Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  __ipow__(self, n: 'int') -> 'Quaternion'
     |      Overloaded ``=**`` operator
     |
     |      :rtype: Quaternion instance
     |
     |      ``q **= N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
     |      an integer.  If ``N``<0 the result is conjugated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> q **= 2
     |          >>> q
     |          >>> q = Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |          >>> q **= 2
     |          >>> q
     |
     |
     |      :seealso: :func:`__pow__`
     |
     |  __neg__(self) -> 'Quaternion'
     |      Overloaded unary ``-`` operator
     |
     |      :rtype: Quaternion or UnitQuaternion
     |
     |      ``-q`` is a quaternion with all its components negated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> -Quaternion([1,2,3,4])
     |          >>> -Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  __pow__(self, n: 'int') -> 'Quaternion'
     |      Overloaded ``**`` operator
     |
     |      :rtype: Quaternion instance
     |
     |      ``q ** N`` computes the product of ``q`` with itself ``N-1`` times, where ``N`` must be
     |      an integer.  If ``N``<0 the result is conjugated.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion([1,2,3,4]) ** 2)
     |          >>> print(Quaternion([1,2,3,4]) ** -1)
     |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) ** 2)
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qpow`
     |
     |  __repr__(self) -> 'str'
     |      Readable representation of pose (superclass method)
     |
     |      :return: readable representation of the pose as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> q
     |
     |  __rmul__(right, left: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``*`` operator
     |
     |      :return: product
     |      :rtype: Quaternion
     |      :raises: ValueError
     |
     |      ``s * q`` is the scalar product, where ``s`` is a scalar.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> 2 * Quaternion([1,2,3,4])
     |          >>> 2 * Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |      :seealso: :func:`__mul__`
     |
     |  __str__(self) -> 'str'
     |      Pretty string representation of quaternion
     |
     |      :return: readable representation of quaternion
     |      :rtype: str
     |
     |      Format the quaternion elements into a single line format.  For example::
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> print(x)
     |          >> q = UnitQuaternion.Rx(0.3)
     |
     |      Note that unit quaternions are denoted by different delimiters for
     |      the vector part.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  __sub__(left, right: 'Quaternion') -> 'Quaternion'
     |      Overloaded ``-`` operator
     |
     |      :return: difference
     |      :rtype: Quaternion, UnitQuaternion
     |      :raises: ValueError
     |
     |      ==============   ==============   ==============  ==========================
     |                 Operands                          Difference
     |      -------------------------------   ------------------------------------------
     |          left             right            type           result
     |      ==============   ==============   ==============  ==========================
     |      Quaternion       Quaternion       Quaternion      elementwise sum
     |      Quaternion       UnitQuaternion   Quaternion      elementwise sum
     |      Quaternion       scalar           Quaternion      subtract from each element
     |      UnitQuaternion   Quaternion       Quaternion      elementwise sum
     |      UnitQuaternion   UnitQuaternion   Quaternion      elementwise sum
     |      UnitQuaternion   scalar           Quaternion      subtract from each element
     |      ==============   ==============   ==============  ==========================
     |
     |      Any other input combinations result in a ValueError.
     |
     |      Note that left and right can have a length greater than 1 in which case:
     |
     |      ====   =====   ====  ================================
     |      left   right   len     operation
     |      ====   =====   ====  ================================
     |       1      1       1    ``diff = left - right``
     |       1      N       N    ``diff[i] = left - right[i]``
     |       N      1       N    ``diff[i] = left[i] - right``
     |       N      N       N    ``diff[i] = left[i] - right[i]``
     |       N      M       -    ``ValueError``
     |      ====   =====   ====  ================================
     |
     |      A scalar of length N is a list, tuple or numpy array.
     |      A 3-vector of length N is a 3xN numpy array, where each column is a 3-vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]) - Quaternion([5,6,7,8])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([1,2,3,4])
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]) - Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]])
     |
     |  conj(self) -> 'Quaternion'
     |      Conjugate of quaternion
     |
     |      :rtype: Quaternion instance
     |
     |      ``q.conj()`` is the quaternion ``q`` with the vector part negated, ie.
     |      :math:`q = s \langle -v_x, -v_y, -v_z \rangle`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion.Pure([1,2,3]).conj())
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qconj`
     |
     |  exp(self, tol: 'float' = 20) -> 'Quaternion'
     |      Exponential of quaternion
     |
     |      :param tol: Tolerance when checking for pure quaternion, in multiples of eps, defaults to 20
     |      :type tol: float, optional
     |      :rtype: Quaternion instance
     |
     |      ``q.exp()`` is the exponential of the quaternion ``q``, ie.
     |
     |      .. math::
     |
     |           e^s \cos \| v \|,  \langle e^s \frac{\vec{v}}{\| \vec{v} \|} \sin \| \vec{v} \| \rangle
     |
     |      For a pure quaternion with vector value :math:`\vec{v}` the the result
     |      is a unit quaternion equivalent to a rotation defined by
     |      :math:`2\vec{v}` intepretted as an Euler vector, that is, parallel to
     |      the axis of rotation and whose norm is the magnitude of rotation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> from math import pi
     |          >>> q = Quaternion([1, 2, 3, 4])
     |          >>> print(q.exp())
     |          >>> q = Quaternion.Pure([pi / 4, 0, 0])
     |          >>> print(q.exp())  # result is a UnitQuaternion
     |          >>> print(q.exp().angvec())
     |
     |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
     |
     |      :seealso: :meth:`Quaternion.log` :meth:`UnitQuaternion.log` :meth:`UnitQuaternion.AngVec` :meth:`UnitQuaternion.EulerVec`
     |
     |  inner(self, other) -> 'float'
     |      Inner product of quaternions
     |
     |      :rtype: float
     |
     |      ``q1.inner(q2)`` is the dot product of the equivalent vectors,
     |      ie. ``numpy.dot(q1.vec, q2.vec)``.
     |      The value of ``q.inner(q)`` is the same as ``q.norm ** 2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).inner(Quaternion([5,6,7,8]))
     |          >>> numpy.dot([1,2,3,4], [5,6,7,8])
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qinner`
     |
     |  log(self) -> 'Quaternion'
     |      Logarithm of quaternion
     |
     |      :rtype: Quaternion instance
     |
     |      ``q.log()`` is the logarithm of the quaternion ``q``, ie.
     |
     |      .. math::
     |
     |           \ln \| q \|,  \langle \frac{\vec{v}}{\| \vec{v} \|} \cos^{-1} \frac{s}{\| q \|} \rangle
     |
     |      For a ``UnitQuaternion`` the logarithm is a pure quaternion whose vector
     |      part :math:`\vec{v}` and :math:`\vec{v}/2` is a Euler vector: parallel
     |      to the axis of rotation and whose norm is the magnitude of rotation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion, UnitQuaternion
     |          >>> from math import pi
     |          >>> q = Quaternion([1, 2, 3, 4])
     |          >>> print(q.log())
     |          >>> q = UnitQuaternion.Rx(pi / 2)
     |          >>> print(q.log())
     |
     |      :reference: `Wikipedia <https://en.wikipedia.org/wiki/Quaternion#Exponential,_logarithm,_and_power_functions>`_
     |
     |      :seealso: :meth:`Quaternion.exp` :meth:`Quaternion.log` :meth:`UnitQuaternion.angvec`
     |
     |  norm(self) -> 'float'
     |      Norm of quaternion
     |
     |      :rtype: float
     |
     |      ``q.norm()`` is the norm or length of the quaternion
     |      :math:`\sqrt{s^2 + v_x^2 + v_y^2 + v_z^2}`
     |
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).norm()
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).norm()
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  unit(self) -> 'UnitQuaternion'
     |      Unit quaternion
     |
     |      :rtype: UnitQuaternion instance
     |
     |      ``q.unit()`` is the quaternion ``q`` normalized to have a unit length.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> q = Quaternion([1,2,3,4])
     |          >>> print(q)
     |          >>> print(q.unit())
     |          >>> print(Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).unit())
     |
     |      Note that the return type is different, a ``UnitQuaternion``, which is
     |      distinguished by the use of double angle brackets to delimit the
     |      vector part.
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qnorm`
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from Quaternion:
     |
     |  Pure(v: 'ArrayLike3') -> 'Quaternion'
     |      Construct a pure quaternion from a vector
     |
     |      :param v: vector
     |      :type v: 3-element array_like
     |
     |      ``Quaternion.Pure(v)`` is a Quaternion with a zero scalar part and the
     |      vector part set to ``v``,
     |      ie. :math:`q = 0 \langle v_x, v_y, v_z \rangle`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> print(Quaternion.Pure([1,2,3]))
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from Quaternion:
     |
     |  matrix
     |      Matrix equivalent of quaternion
     |
     |      :rtype: Numpy array, shape=(4,4)
     |
     |      ``q.matrix`` is a 4x4 matrix which encodes the arithmetic rules of Hamilton multiplication.
     |      This matrix, multiplied by the 4-vector equivalent of a second quaternion, results in the 4-vector
     |      equivalent of the Hamilton product.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).matrix
     |          >>> Quaternion([1,2,3,4]) * Quaternion([5,6,7,8])   # Hamilton product
     |          >>> Quaternion([1,2,3,4]).matrix @ Quaternion([5,6,7,8]).vec  # matrix-vector product
     |
     |      :seealso: :func:`~spatialmath.base.quaternions.qmatrix`
     |
     |  s
     |      Scalar part of quaternion
     |
     |      :return: scalar part of quaternion
     |      :rtype: float or numpy.ndarray
     |
     |      ``q.s`` is the scalar part.  If `len(q)` is:
     |
     |          - 1, return a scalar float
     |          - N>1, return a NumPy array shape=(N,) is returned.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).s
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).s
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (4,)
     |      :rtype: tuple
     |
     |  v
     |      Vector part of quaternion
     |
     |      :return: vector part of quaternion
     |      :rtype: NumPy ndarray
     |
     |      ``q.v`` is the vector part.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(3,)
     |          - N>1, return a NumPy array shape=(N,3).
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).v
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).v
     |
     |  vec
     |      Quaternion as a vector
     |
     |      :return: quaternion expressed as a 4-vector
     |      :rtype: numpy ndarray, shape=(4,)
     |
     |      ``q.vec`` is the quaternion as a vector.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(4,)
     |          - N>1, return a NumPy array shape=(N,4).
     |
     |      The quaternion coefficients are in the order (s, vx, vy, vz), ie. with
     |      the scalar (real part) first.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).vec
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec
     |
     |  vec_xyzs
     |      Quaternion as a vector
     |
     |      :return: quaternion expressed as a 4-vector
     |      :rtype: numpy ndarray, shape=(4,)
     |
     |      ``q.vec_xyzs`` is the quaternion as a vector.  If `len(q)` is:
     |
     |          - 1, return a NumPy array shape=(4,)
     |          - N>1, return a NumPy array shape=(N,4).
     |
     |      The quaternion coefficients are in the order (vx, vy, vz, s), ie. with
     |      the scalar (real part) last. This is useful when exporting to other
     |      packages like three.js or pybullet.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Quaternion
     |          >>> Quaternion([1,2,3,4]).vec_xyzs
     |          >>> Quaternion([np.r_[1,2,3,4], np.r_[5,6,7,8]]).vec_xyzs
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

DATA
    ArrayLike = typing.Union[float, typing.List[float], typing.T...ndarray...
    ArrayLike2 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike3 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike4 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLike6 = typing.Union[typing.List[float], typing.Tuple[fl...typing...
    ArrayLikePure = typing.Union[typing.List[float], typing.Tuple[fl...nda...
    Callable = typing.Callable
        Deprecated alias to collections.abc.Callable.

        Callable[[int], str] signifies a function that takes a single
        parameter of type int and returns a str.

        The subscription syntax must always be used with exactly two
        values: the argument list and the return type.
        The argument list must be a list of types, a ParamSpec,
        Concatenate or ellipsis. The return type must be a single type.

        There is no syntax to indicate optional or keyword arguments;
        such function types are rarely used as callback types.

    Color = typing.Union[str, typing.List[float], typing.Tup...typing.Lite...
    DTypeLike = typing.Union[numpy.dtype[typing.Any], NoneType, ...e_like....
    Iterator = typing.Iterator
        A generic version of collections.abc.Iterator.

    L = typing.Literal
        Special typing form to define literal types (a.k.a. value types).

        This form can be used to indicate to type checkers that the corresponding
        variable or function parameter has a value equivalent to the provided
        literal (or one of several literals)::

            def validate_simple(data: Any) -> Literal[True]:  # always returns True
                ...

            MODE = Literal['r', 'rb', 'w', 'wb']
            def open_helper(file: str, mode: MODE) -> str:
                ...

            open_helper('/some/path', 'r')  # Passes type check
            open_helper('/other/path', 'typo')  # Error in type checker

        Literal[...] cannot be subclassed. At runtime, an arbitrary value
        is allowed as type argument to Literal[...], but type checkers may
        impose restrictions.

    List = typing.List
        A generic version of list.

    NDArray = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Points2 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Points3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    QuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy...
    R1 = numpy.ndarray[typing.Tuple[typing.Literal[1]], numpy.dtype[numpy....
    R1x1 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[1]...
    R1x2 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[2]...
    R1x3 = numpy.ndarray[typing.Tuple[typing.Literal[1], typing.Literal[3]...
    R2 = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[numpy....
    R2x1 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[1]...
    R2x2 = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Literal[2]...
    R3 = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[numpy....
    R3x1 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[1]...
    R3x3 = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Literal[3]...
    R4 = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[numpy....
    R4x4 = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Literal[4]...
    R6 = numpy.ndarray[typing.Tuple[typing.Literal[6]], numpy.dtype[numpy....
    R6x6 = numpy.ndarray[typing.Tuple[typing.Literal[6], typing.Literal[6]...
    R8 = numpy.ndarray[typing.Tuple[typing.Literal[8]], numpy.dtype[numpy....
    R8x8 = numpy.ndarray[typing.Tuple[typing.Literal[8], typing.Literal[8]...
    RNx3 = numpy.ndarray[typing.Any, numpy.dtype[+_ScalarType_co]]
    Rn = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.Literal...
    SE2Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SE3Array = numpy.ndarray[typing.Tuple[typing.Literal[4], typing.Litera...
    SEnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    SO2Array = numpy.ndarray[typing.Tuple[typing.Literal[2], typing.Litera...
    SO3Array = numpy.ndarray[typing.Tuple[typing.Literal[3], typing.Litera...
    SOnArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    Self = typing.Self
        Used to spell the type of "self" in classes.

        Example::

            from typing import Self

            class Foo:
                def return_self(self) -> Self:
                    ...
                    return self

        This is especially useful for:
            - classmethods that are used as alternative constructors
            - annotating an `__enter__` method which returns self

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

    Type = typing.Type
        Deprecated alias to builtins.type.

        builtins.type or typing.Type can be used to annotate class objects.
        For example, suppose we have the following classes::

            class User: ...  # Abstract base for User classes
            class BasicUser(User): ...
            class ProUser(User): ...
            class TeamUser(User): ...

        And a function that takes a class argument that's a subclass of
        User and returns an instance of the corresponding class::

            def new_user[U](user_class: Type[U]) -> U:
                user = user_class()
                # (Here we could write the user object to a database)
                return user

            joe = new_user(BasicUser)

        At this point the type checker knows that joe has type BasicUser.

    Union = typing.Union
        Union type; Union[X, Y] means either X or Y.

        On Python 3.10 and higher, the | operator
        can also be used to denote unions;
        X | Y means the same thing to the type checker as Union[X, Y].

        To define a union, use e.g. Union[int, str]. Details:
        - The arguments must be types and there must be at least one.
        - None as an argument is a special case and is replaced by
          type(None).
        - Unions of unions are flattened, e.g.::

            assert Union[Union[int, str], float] == Union[int, str, float]

        - Unions of a single argument vanish, e.g.::

            assert Union[int] == int  # The constructor actually returns int

        - Redundant arguments are skipped, e.g.::

            assert Union[int, str, int] == Union[int, str]

        - When comparing unions, the argument order is ignored, e.g.::

            assert Union[int, str] == Union[str, int]

        - You cannot subclass or instantiate a union.
        - You can use Optional[X] as a shorthand for Union[X, None].

    UnitQuaternionArray = numpy.ndarray[typing.Tuple[typing.Literal[4]], n...
    se2Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    se3Array = numpy.ndarray[typing.Tuple[typing.Literal[4]], numpy.dtype[...
    senArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...
    so2Array = numpy.ndarray[typing.Tuple[typing.Literal[2]], numpy.dtype[...
    so3Array = numpy.ndarray[typing.Tuple[typing.Literal[3]], numpy.dtype[...
    sonArray = typing.Union[numpy.ndarray[typing.Tuple[typing.L...typing.L...

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\quaternion.py

spatialmath-python.spatialvector
Python Library Documentation: module spatialmath.spatialvector in spatialmath

NAME
    spatialmath.spatialvector - A set of cooperating classes to support Featherstone's spatial vector formalism

DESCRIPTION

    .. inheritance-diagram:: spatialmath.spatialvector
       :top-classes: collections.UserList
       :parts: 1

    .. note:: Compared to Featherstone's papers these spatial vectors have the
        translational components first, followed by rotational components.

CLASSES
    spatialmath.baseposelist.BasePoseList(collections.UserList, abc.ABC)
        SpatialInertia
        SpatialVector
            SpatialF6
                SpatialForce
                SpatialMomentum
            SpatialM6
                SpatialAcceleration
                SpatialVelocity

    class SpatialAcceleration(SpatialM6)
     |  SpatialAcceleration(value=None)
     |
     |  Spatial acceleration class
     |
     |  Concrete subclass of SpatialM6 that represents the
     |  translational and rotational acceleration of a rigid-body moving in 3D space.
     |
     |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialAcceleration
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialVelocity`
     |
     |  Method resolution order:
     |      SpatialAcceleration
     |      SpatialM6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value=None)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialM6:
     |
     |  cross(self, other)
     |      Spatial vector cross product
     |
     |      :param other: spatial motion vector
     |      :type other: SpatialM6 instance
     |      :return: cross product of spatial vectors
     |      :rtype: SpatialF6 instance if ``other`` is SpatialF6 instance
     |      :rtype: SpatialM6 instance if ``other`` is SpatialM6 instance
     |
     |      ``v1.cross(v2)`` is a spatial vector cross product whose result depends
     |      on the SpatialVector subclass of ``v2``:
     |
     |      - if :math:`\vec{m} \in \mat{M}^6` is a spatial motion vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{m} = \vec{v} \times \vec{m}` or the ``crm()`` function.
     |
     |      - if :math:`\vec{f} \in \mat{F}^6` is a spatial force vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{f} = \vec{v} \times^* \vec{f}` or the ``crm()`` function.
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialF6(SpatialVector)
     |  SpatialF6(value)
     |
     |  Spatial 6-vector abstract force superclass
     |
     |  Abstract superclass that represents the vector space for spatial force.
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialForce`, :func:`~spatialmath.spatialvector.SpatialMomentum`.
     |
     |  Method resolution order:
     |      SpatialF6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  dot(self, value)
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'__init__'})
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialForce(SpatialF6)
     |  SpatialForce(value=None)
     |
     |  Spatial force class
     |
     |  Concrete subclass of SpatialF6 and represents the
     |  translational and rotational forces and torques acting on a rigid-body in 3D space.
     |
     |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialForce
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialF6`, :func:`~spatialmath.spatialvector.SpatialMomentum`
     |
     |  Method resolution order:
     |      SpatialForce
     |      SpatialF6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value=None)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialF6:
     |
     |  dot(self, value)
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialInertia(spatialmath.baseposelist.BasePoseList)
     |  SpatialInertia(m=None, r=None, I=None)
     |
     |  Spatial inertia class
     |
     |  Spatial inertia of a body in 3D space.
     |
     |  ========   ===========================================================
     |  Operator   Operation
     |  ========   ===========================================================
     |  ``+``      addition of spatial inertias of joined bodies
     |  ``*``      acceleration x inertia is force
     |  ========   ===========================================================
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialF6`, :func:`~spatialmath.spatialvector.SpatialVelocity`, :func:`~spatialmath.spatialvector.SpatialAcceleration`, :func:`~spatialmath.spatialvector.SpatialForce`, :func:`~spatialmath.spatialvector.SpatialMomentum`.
     |
     |  Method resolution order:
     |      SpatialInertia
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __add__(left, right)
     |      Spatial inertia addition
     |      :param left:
     |      :param right:
     |      :return:
     |      :raises TypeError: attempting to add invalid type to SpatialInertia
     |
     |      - ``SI1 + SI2`` is the SpatialInertia of a composite body when bodies with
     |         SpatialInertia ``SI1`` and ``SI2`` are connected.
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __init__(self, m=None, r=None, I=None)
     |      Create a new spatial inertia
     |
     |      :param m: mass
     |      :type m: float
     |      :param r: centre of mass relative to link frame
     |      :type r: 3-element array_like
     |      :param I: inertia about the centre of mass, axes aligned with link frame
     |      :type I: numpy.array, shape=(6,6)
     |
     |      - ``SpatialInertia(m, r, I)`` is a spatial inertia object for a rigid-body
     |        with mass ``m``, centre of mass at ``r`` relative to the link frame, and an
     |        inertia matrix ``I`` (3x3) about the centre of mass.
     |
     |      - ``SpatialInertia(I)`` is a spatial inertia object with a value equal
     |        to ``I`` (6x6).
     |
     |      :SymPy: supported
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :param other: spatial acceleration vector
     |      :type other: SpatialAcceleration instance
     |      :return: force
     |      :rtype: SpatialForce instance if ``other`` is SpatialAcceleration instance
     |      :rtype: SpatialMomentum instance if ``other`` is SpatialVelocity instance
     |
     |      - ``I * a`` is the SpatialForce required for a body with SpatialInertia ``I`` to accelerate with
     |        the SpatialAcceleration ``a``.
     |      - ``I * v`` is the SpatialMomemtum of a body with SpatialInertia ``I`` and SpatialVelocity ``v``.
     |
     |  __repr__(self)
     |      Convert to string
     |
     |      s = SI.char() is a string showing spatial inertia parameters in a
     |      compact format.
     |      If SI is an array of spatial inertia objects return a string with the
     |      inertia values in a vertical list.
     |
     |      See also SpatialInertia.display.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :param other: spatial acceleration vector
     |      :type other: SpatialAcceleration instance
     |      :return: force
     |      :rtype: SpatialForce instance if ``other`` is SpatialAcceleration instance
     |      :rtype: SpatialMomentum instance if ``other`` is SpatialVelocity instance
     |
     |      - ``a * I`` is the SpatialForce required for a body with SpatialInertia ``I`` to accelerate with
     |        the SpatialAcceleration ``a``.
     |      - ``v * I`` is the SpatialMomemtum of a body with SpatialInertia ``I`` and SpatialVelocity ``v``.
     |
     |  __str__(self)
     |      Return str(self).
     |
     |  isvalid(self, x, check)
     |      Test if matrix is valid spatial inertia
     |
     |      :param x: matrix to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,6).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,6)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialM6(SpatialVector)
     |  SpatialM6(value)
     |
     |  Spatial 6-vector abstract motion superclass
     |
     |  Abstract superclass that represents the vector space for spatial motion.
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialVelocity`, :func:`~spatialmath.spatialvector.SpatialAcceleration`
     |
     |  Method resolution order:
     |      SpatialM6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  cross(self, other)
     |      Spatial vector cross product
     |
     |      :param other: spatial motion vector
     |      :type other: SpatialM6 instance
     |      :return: cross product of spatial vectors
     |      :rtype: SpatialF6 instance if ``other`` is SpatialF6 instance
     |      :rtype: SpatialM6 instance if ``other`` is SpatialM6 instance
     |
     |      ``v1.cross(v2)`` is a spatial vector cross product whose result depends
     |      on the SpatialVector subclass of ``v2``:
     |
     |      - if :math:`\vec{m} \in \mat{M}^6` is a spatial motion vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{m} = \vec{v} \times \vec{m}` or the ``crm()`` function.
     |
     |      - if :math:`\vec{f} \in \mat{F}^6` is a spatial force vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{f} = \vec{v} \times^* \vec{f}` or the ``crm()`` function.
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'__init__'})
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialMomentum(SpatialF6)
     |  SpatialMomentum(value=None)
     |
     |  Spatial momentum class
     |
     |  Concrete subclass of SpatialF6 and represents the
     |  translational and rotational momentum of a rigid-body in 3D space.
     |
     |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialMomentum
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialF6`,  :func:`~spatialmath.spatialvector.SpatialForce`
     |
     |  Method resolution order:
     |      SpatialMomentum
     |      SpatialF6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value=None)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialF6:
     |
     |  dot(self, value)
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialVector(spatialmath.baseposelist.BasePoseList)
     |  SpatialVector(value)
     |
     |  Spatial 6-vector abstract superclass
     |
     |  This class has two abstract subclasses, which each have concrete subclasses.
     |  Key characteristics:
     |
     |  - 6D vectors that represent velocity, acceleration, momentum and force of
     |    bodies in 3D.
     |  - inherit list-like properties from ``SMUserList`` class
     |  - support operators:
     |
     |  ========   ===========================================================
     |  Operator   Operation
     |  ========   ===========================================================
     |  ``+``      addition of spatial vectors of the same subclass
     |  ``-``      subtraction of spatial vectors of the same subclass
     |  ``-``      unary minus
     |  ``*``      see table below
     |  ``^``      cross product x or x*
     |  ========   ===========================================================
     |
     |
     |  Certain subtypes can be multiplied
     |
     |  ===================   ====================  ===================  =========================
     |              Multiplicands                   Product
     |  ------------------------------------------  ----------------------------------------------
     |  left                  right                 type                 operation
     |  ===================   ====================  ===================  =========================
     |  SE3, Twist3           SpatialVelocity       SpatialVelocity      adjoint product
     |  SE3, Twist3           SpatialAcceleration   SpatialAcceleration  adjoint product
     |  SE3, Twist3           SpatialMomentum       SpatialMomentum      adjoint transpose product
     |  SE3, Twist3           SpatialForce          SpatialForce         adjoint transpose product
     |  SpatialAcceleration   SpatialInertia        SpatialForce         matrix-vector product**
     |  SpatialVelocity       SpatialInertia        SpatialMomentum      matrix-vector product**
     |  ===================   ====================  ===================  =========================
     |
     |  ** indicates commutative operator.
     |
     |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialVelocity spatialmath.spatialvector.SpatialAcceleration spatialmath.spatialvector.SpatialForce spatialmath.spatialvector.SpatialMomentum
     |     :top-classes: spatialmath.spatialvector.SpatialVector
     |     :parts: 1
     |
     |  **References:**
     |
     |  - "Robot Dynamics Algorithms", R. Featherstone, volume 22,
     |    Springer International Series in Engineering and Computer Science,
     |    Springer, 1987.
     |  - "A beginner's guide to 6-d vectors (part 1)", R. Featherstone,
     |    IEEE Robotics Automation Magazine, 17(3):83-94, Sep. 2010.
     |  - `Online notes <http://users.cecs.anu.edu.au/~roy/spatial>`_
     |    Methods:
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialF6`, :func:`~spatialmath.spatialvector.SpatialVelocity`, :func:`~spatialmath.spatialvector.SpatialAcceleration`, :func:`~spatialmath.spatialvector.SpatialForce`, :func:`~spatialmath.spatialvector.SpatialMomentum`.
     |
     |  Method resolution order:
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __init__(self, value)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class SpatialVelocity(SpatialM6)
     |  SpatialVelocity(value=None)
     |
     |  Spatial velocity class
     |
     |  Concrete subclass of SpatialM6 that represents the
     |  translational and rotational velocity of a rigid-body moving in 3D space.
     |
     |  .. inheritance-diagram:: spatialmath.spatialvector.SpatialVelocity
     |     :top-classes: collections.UserList
     |     :parts: 1
     |
     |  :seealso: :func:`~spatialmath.spatialvector.SpatialM6`, :func:`~spatialmath.spatialvector.SpatialAcceleration`
     |
     |  Method resolution order:
     |      SpatialVelocity
     |      SpatialM6
     |      SpatialVector
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __init__(self, value=None)
     |      Create a new spatial vector (abstract superclass)
     |
     |      :param value: Value of the
     |
     |      - ``SpatialVector(vec)`` is a spatial vector constructed from the 6-element array-like ``vec``
     |      - ``SpatialVector([V1, V2, ... VN])`` is a spatial vector array with N elements, constructed from the 6-element
     |        array-like values ``Vi``
     |      - ``SpatialVector(A)`` is a spatial vector array with N elements, constructed from the columns of the 6xN
     |        array ``A``.
     |
     |  __matmul__(self, other)
     |      Overloaded ``@`` operator (superclass method)
     |
     |      :param other: spatial velocity vector
     |      :type other: SpatialVelocity or SpatialMomentum instance
     |      :return: cross product of spatial vectors
     |      :rtype: SpatialAcceleration instance if ``other`` is SpatialVelocity instance
     |      :rtype: SpatialMomentum instance if ``other`` is SpatialForce instance
     |
     |      This operator implements the spatial vector cross product.
     |
     |      - ``v1 @v2`` is spatial acceleration given spatial velocities
     |        ``v1`` and ``v2`` or :math:`\vec{v}_1 \times \vec{v}_2`
     |      - ``v1 @ m2`` is spatial force given spatial velocity
     |        ``v1`` and spatial momentum ``m2`` or :math:`\vec{v}_1 \times^* \vec{m}_2`
     |
     |      .. note:: The ``@`` operator was chosen because it has high precendence
     |          and is somewhat invocative of multiplication.
     |
     |      :seealso: :func:`~spatialmath.spatialvector.SpatialVelocity.cross`
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialM6:
     |
     |  cross(self, other)
     |      Spatial vector cross product
     |
     |      :param other: spatial motion vector
     |      :type other: SpatialM6 instance
     |      :return: cross product of spatial vectors
     |      :rtype: SpatialF6 instance if ``other`` is SpatialF6 instance
     |      :rtype: SpatialM6 instance if ``other`` is SpatialM6 instance
     |
     |      ``v1.cross(v2)`` is a spatial vector cross product whose result depends
     |      on the SpatialVector subclass of ``v2``:
     |
     |      - if :math:`\vec{m} \in \mat{M}^6` is a spatial motion vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{m} = \vec{v} \times \vec{m}` or the ``crm()`` function.
     |
     |      - if :math:`\vec{f} \in \mat{F}^6` is a spatial force vector fixed in a
     |        body with velocity :math:`\vec{v}` then
     |        :math:`\dvec{f} = \vec{v} \times^* \vec{f}` or the ``crm()`` function.
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SpatialVector:
     |
     |  __add__(left, right)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: sum of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to add SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to add SpatialVectors with different numbers of values
     |
     |      ``v1 + v2`` is a spatial vector of the same type as ``v1`` and ``v2`` whose value is
     |      the element-wise sum of ``v1`` and ``v2``.  If both are arrays of spatial vectors V1 (1xN) and
     |      V2 (1xN) the result is an array (1xN).
     |
     |      :seealso: :func:`__sub__`
     |
     |  __getitem__(self, i)
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __neg__(self)
     |      Overloaded unary ``-`` operator (superclass method)
     |
     |      :return: negative of spatial vector
     |      :rtype: SpatialVector subclass instance
     |
     |      ``-v`` is a spatial vector of the same type as ``v`` whose value is
     |      the element-wise negative of ``v``.
     |
     |      :seealso: :func:`__sub__`
     |
     |  __repr__(self)
     |      :return:
     |      SpatialVec6.display Display parameters
     |
     |      V.display() displays the spatial vector parameters in compact single line format.
     |      If V is an array of spatial vector objects it displays one per line.
     |
     |      Notes:
     |
     |       - This method is invoked implicitly at the command line when the result
     |         of an expression is a serial vector subclass object and the command has
     |         no trailing semicolon.
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator (superclass method)
     |
     |      :return: transformed spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: for incompatible left operand
     |
     |      ``X * S`` transforms the spatial vector ``S`` by the relative pose ``X``
     |      which may be either an ``SE3`` or ``Twist3`` instance.  The spatial
     |      vector is premultiplied by the adjoint of ``X`` or adjoint transpose
     |      of ``X`` depending on the SpatialVector subclass of ``S``.
     |
     |      ===========  ====================  ===================  =========================
     |                 Multiplicands                   Product
     |      -------------------------------   -----------------------------------
     |      left         right                type                 operation
     |      ===========  ====================  ===================  =========================
     |      SE3, Twist3  SpatialVelocity       SpatialVelocity      adjoint product
     |      SE3, Twist3  SpatialAcceleration   SpatialAcceleration  adjoint product
     |      SE3, Twist3  SpatialMomentum       SpatialMomentum      adjoint transpose product
     |      SE3, Twist3  SpatialForce          SpatialForce         adjoint transpose product
     |      ===========  ====================  ===================  =========================
     |
     |  __str__(self)
     |      Pretty string representation (superclass method)
     |
     |      :return: readable representation of the spatial vector
     |      :rtype: str
     |
     |      - ``s = str(v)`` is a string showing spatial vector parameters in a
     |      compact single line format.
     |
     |      If V is an array of spatial vector objects return a string with one
     |      line per element.
     |
     |  __sub__(left, right)
     |      Overloaded ``-`` operator (superclass method)
     |
     |      :return: difference of spatial vectors
     |      :rtype: SpatialVector subclass instance
     |      :raises TypeError: attempting to subtract SpatialVectors of different subclass
     |      :raises ValueErrror: attempting to subtract SpatialVectors with different numbers of values
     |
     |      ``v1 - v2`` is a spatial vector of the same type as ``v1`` and ``v2``
     |      whose value is the element-wise difference of ``v1`` and ``v2``.  If
     |      both are arrays of spatial vectors V1 (1xN) and V2 (1xN) the result is
     |      an array (1xN).
     |
     |      :seealso: :func:`__add__`, :func:`__neg__`
     |
     |  isvalid(self, x, check)
     |      Test if vector is valid spatial vector
     |
     |      :param x: vector to test
     |      :type x: numpy.ndarray
     |      :arg check: ignored
     |      :type check: bool
     |      :return: True if the matrix has shape (6,).
     |      :rtype: bool
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from SpatialVector:
     |
     |  shape
     |      Shape of the object's interal matrix representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __eq__(self, other)
     |      Return self==value.
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from collections.UserList:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\spatialvector.py

spatialmath-python.spline
Python Library Documentation: module spatialmath.spline in spatialmath

NAME
    spatialmath.spline - Classes for parameterizing a trajectory in SE3 with splines.

CLASSES
    abc.ABC(builtins.object)
        SplineSE3
            BSplineSE3
            InterpSplineSE3
    builtins.object
        SplineFit

    class BSplineSE3(SplineSE3)
     |  BSplineSE3(control_poses: List[spatialmath.pose3d.SE3], degree: int = 3, knots: Optional[List[float]] = None) -> None
     |
     |  A class to parameterize a trajectory in SE3 with a 6-dimensional B-spline.
     |
     |  The SE3 control poses are converted to se3 twists (the lie algebra) and a B-spline
     |  is created for each dimension of the twist, using the corresponding element of the twists
     |  as the control point for the spline.
     |
     |  For detailed information about B-splines, please see this wikipedia article.
     |  https://en.wikipedia.org/wiki/Non-uniform_rational_B-spline
     |
     |  Method resolution order:
     |      BSplineSE3
     |      SplineSE3
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __call__(self, t: float) -> spatialmath.pose3d.SE3
     |      Returns pose of spline at t.
     |
     |      t: Normalized time value [0,1] to evaluate the spline at.
     |
     |  __init__(self, control_poses: List[spatialmath.pose3d.SE3], degree: int = 3, knots: Optional[List[float]] = None) -> None
     |      Construct BSplineSE3 object. The default arguments generate a cubic B-spline
     |      with uniformly spaced knots.
     |
     |      - control_poses: list of SE3 objects that govern the shape of the spline.
     |      - degree: int that controls degree of the polynomial that governs any given point on the spline.
     |      - knots: list of floats that govern which control points are active during evaluating the spline
     |      at a given t input. If none, they are automatically, uniformly generated based on number of control poses and
     |      degree of spline on the range [0,1].
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SplineSE3:
     |
     |  visualize(self, sample_times: List[float], input_trajectory: Optional[List[spatialmath.pose3d.SE3]] = None, pose_marker_length: float = 0.2, animate: bool = False, repeat: bool = True, ax: Optional[matplotlib.axes._axes.Axes] = None) -> None
     |      Displays an animation of the trajectory with the control poses against an optional input trajectory.
     |
     |      Args:
     |          sample_times: which times to sample the spline at and plot
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from SplineSE3:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class InterpSplineSE3(SplineSE3)
     |  InterpSplineSE3(timepoints: List[float], control_poses: List[spatialmath.pose3d.SE3], *, normalize_time: bool = False, bc_type: str = 'not-a-knot') -> None
     |
     |  Class for an interpolated trajectory in SE3, as a function of time, through control_poses with a cubic spline.
     |
     |  A combination of scipy.interpolate.CubicSpline and scipy.spatial.transform.RotationSpline (itself also cubic)
     |  under the hood.
     |
     |  Method resolution order:
     |      InterpSplineSE3
     |      SplineSE3
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __call__(self, t: float) -> spatialmath.pose3d.SE3
     |      Compute function value at t.
     |      Return:
     |          pose: SE3
     |
     |  __init__(self, timepoints: List[float], control_poses: List[spatialmath.pose3d.SE3], *, normalize_time: bool = False, bc_type: str = 'not-a-knot') -> None
     |      Construct a InterpSplineSE3 object
     |
     |      Extends the scipy CubicSpline object
     |      https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.CubicSpline.html#cubicspline
     |
     |      Args :
     |          timepoints : list of times corresponding to provided poses
     |          control_poses : list of SE3 objects that govern the shape of the spline.
     |          normalize_time : flag to map times into the range [0, 1]
     |          bc_type : boundary condition provided to scipy CubicSpline backend.
     |                    string options: ["not-a-knot" (default), "clamped", "natural", "periodic"].
     |                    For tuple options and details see the scipy docs link above.
     |
     |  derivative(self, t: float) -> spatialmath.twist.Twist3
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from SplineSE3:
     |
     |  visualize(self, sample_times: List[float], input_trajectory: Optional[List[spatialmath.pose3d.SE3]] = None, pose_marker_length: float = 0.2, animate: bool = False, repeat: bool = True, ax: Optional[matplotlib.axes._axes.Axes] = None) -> None
     |      Displays an animation of the trajectory with the control poses against an optional input trajectory.
     |
     |      Args:
     |          sample_times: which times to sample the spline at and plot
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from SplineSE3:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class SplineFit(builtins.object)
     |  SplineFit(time_data: List[float], pose_data: List[spatialmath.pose3d.SE3]) -> None
     |
     |  A general class to fit various SE3 splines to data.
     |
     |  Methods defined here:
     |
     |  __init__(self, time_data: List[float], pose_data: List[spatialmath.pose3d.SE3]) -> None
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  angular_errors(self) -> List[float]
     |
     |  euclidean_errors(self) -> List[float]
     |
     |  max_angular_error(self) -> float
     |
     |  max_euclidean_error(self) -> float
     |
     |  stochastic_downsample_interpolation(self, epsilon_xyz: float = 0.001, epsilon_angle: float = 0.1, normalize_time: bool = True, bc_type: str = 'not-a-knot', check_type: str = 'local') -> Tuple[spatialmath.spline.InterpSplineSE3, List[int]]
     |      Uses a random dropout to downsample a trajectory with an interpolated spline. Keeps the start and
     |      end points of the trajectory. Takes a random order of the remaining indices, and then checks the error bound
     |      of just that point if check_type=="local", checks the error of the whole trajectory is check_type=="global".
     |      Local is **much** faster.
     |
     |          Return:
     |              downsampled interpolating spline,
     |              list of removed indices from input data
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object

    class SplineSE3(abc.ABC)
     |  SplineSE3() -> None
     |
     |  Method resolution order:
     |      SplineSE3
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __call__(self, t: float) -> spatialmath.pose3d.SE3
     |      Call self as a function.
     |
     |  __init__(self) -> None
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  visualize(self, sample_times: List[float], input_trajectory: Optional[List[spatialmath.pose3d.SE3]] = None, pose_marker_length: float = 0.2, animate: bool = False, repeat: bool = True, ax: Optional[matplotlib.axes._axes.Axes] = None) -> None
     |      Displays an animation of the trajectory with the control poses against an optional input trajectory.
     |
     |      Args:
     |          sample_times: which times to sample the spline at and plot
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'__call__'})

DATA
    List = typing.List
        A generic version of list.

    Optional = typing.Optional
        Optional[X] is equivalent to Union[X, None].

    Tuple = typing.Tuple
        Deprecated alias to builtins.tuple.

        Tuple[X, Y] is the cross-product type of X and Y.

        Example: Tuple[T1, T2] is a tuple of two elements corresponding
        to type variables T1 and T2.  Tuple[int, float, str] is a tuple
        of an int, a float and a string.

        To specify a variable-length tuple of homogeneous type, use Tuple[T, ...].

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\spline.py

spatialmath-python.twist
Python Library Documentation: module spatialmath.twist in spatialmath

NAME
    spatialmath.twist

DESCRIPTION
    # Part of Spatial Math Toolbox for Python
    # Copyright (c) 2000 Peter Corke
    # MIT Licence, see details in top-level file: LICENCE

CLASSES
    spatialmath.baseposelist.BasePoseList(collections.UserList, abc.ABC)
        BaseTwist
            Twist2
            Twist3

    class BaseTwist(spatialmath.baseposelist.BasePoseList)
     |  Superclass for 3D and 2D twist objects
     |
     |  Subclasses are:
     |
     |  - ``Twist3`` representing rigid-body motion in 3D as a 6-vector
     |  - ``Twist2`` representing rigid-body motion in 2D as a 3-vector
     |
     |  A twist is the unique elements of the logarithm of the corresponding SE(N)
     |  matrix.
     |
     |  Arithmetic operators are overloaded but the operation they perform depend
     |  on the types of the operands.  For example:
     |
     |  - ``*`` will compose two instances of the same subclass, and the result will be
     |    an instance of the same subclass, since this is a group operator.
     |
     |  These classes all inherit from ``UserList`` which enables them to
     |  represent a sequence of values, ie. a ``Twist3`` instance can contain
     |  a sequence of twists.  Most of the Python ``list`` operators
     |  are applicable:
     |
     |  .. runblock:: pycon
     |      >>> from spatialmath import Twist3
     |      >>> x = Twist3()  # new instance with zero value
     |      >>> len(x)     # it is a sequence of one value
     |      >>> x.append(x)  # append to itself
     |      >>> len(x)       # it is a sequence of two values
     |      >>> x[1]         # the element has a 4x4 matrix value
     |      >>> x[1] = SE3.Rx(0.3).Twist3()  # set an elements of the sequence
     |      >>> x.reverse()         # reverse the elements in the sequence
     |      >>> del x[1]            # delete an element
     |
     |  :References:
     |
     |      - "Mechanics, planning and control"
     |        Park & Lynch, Cambridge, 2016.
     |
     |  This class is subclassed for the 3D and 2D cases
     |
     |  .. inheritance-diagram:: spatialmath.twist.Twist3 spatialmath.twist.Twist2
     |     :top-classes: collections.UserList
     |     :parts: 2
     |
     |  Method resolution order:
     |      BaseTwist
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  __eq__(left, right)
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      ``S1 == S2`` is True if ``S1` is elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 == S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 == S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __init__(self)
     |      Initialize self.  See help(type(self)) for accurate signature.
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :rtype: bool
     |
     |      ``S1 == S2`` is True if ``S1` is not elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 != S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 != S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __truediv__(left, right)
     |
     |  inv(self)
     |      Inverse of Twist (superclass method)
     |
     |      :return: inverse
     |      :rtype: Twist instance
     |
     |      Compute the inverse of each of the values within the twist instance.
     |      The inverse is the negative of the twist vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3(SE3.Rand())
     |          >>> S
     |          >>> S.inv()
     |          >>> S * S.inv()
     |
     |  prod(self)
     |      Product of twists (superclass method)
     |
     |      :return: Product of elements
     |      :rtype: Twist2 or Twist3
     |
     |      For a twist instance with N values return the matrix product of those
     |      elements :math:`\prod_i=0^{N-1} S_i`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx([0.2, 0.3, 0.4])
     |          >>> len(S)
     |          >>> S.prod()
     |          >>> Twist3.Rx(0.9)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  S
     |      Twist as a vector (superclass property)
     |
     |      :return: Twist vector
     |      :rtype: ndarray(N)
     |
     |      - ``X.S`` is a 3-vector if X is a ``Twist2`` instance, and a 6-vector if
     |        X is a ``Twist3`` instance.
     |
     |      .. note::
     |
     |          - the vector is the unique elements of the se(N) representation.
     |          - the vector is sometimes referred to as the twist coordinate vector.
     |          - if ``len(X)`` > 1 then return a list of vectors.
     |
     |  isprismatic
     |      Test for prismatic twist (superclass property)
     |
     |      :return: Whether twist is purely prismatic
     |      :rtype: bool
     |
     |      A prismatic twist has :math:`\vec{\omega} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isprismatic
     |          >>> x = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> x.isprismatic
     |
     |  isrevolute
     |      Test for revolute twist (superclass property)
     |
     |      :return: Whether twist is purely revolute
     |      :rtype: bool
     |
     |      A revolute twist has :math:`\vec{v} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isrevolute
     |          >>> x = Twist3.UnitRevolute([1,2,3], [0,0,0])
     |          >>> x.isrevolute
     |
     |  isunit
     |      Test for unit twist (superclass property)
     |
     |      :return: Whether twist is a unit-twist
     |      :rtype: bool
     |
     |      A unit twist is one with a norm of 1, ie. :math:`\| S \| = 1`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3([1,2,3,4,5,6])
     |          >>> S.isunit()
     |          >>> S = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> S.isunit()
     |
     |  theta
     |      Twist angle (superclass method)
     |
     |      :return: magnitude of rotation (1x1) about the twist axis in radians
     |      :rtype: float
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset({'_identity', 'isvalid', 'shape'})
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Static methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  isvalid(x, check=True)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  shape
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __mul__(self, n)
     |
     |  __radd__(self, other)
     |
     |  __repr__(self)
     |      Return repr(self).
     |
     |  __rmul__ = __mul__(self, n)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class Twist2(BaseTwist)
     |  Twist2(arg=None, w=None, check=True)
     |
     |  Method resolution order:
     |      Twist2
     |      BaseTwist
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  SE2(self, theta=1, unit='rad')
     |      Convert 2D twist to SE(2) matrix
     |
     |      :return: an SE(2) representation
     |      :rtype: SE3 instance
     |
     |      ``S.SE2()`` is an SE2 object representing the homogeneous transformation
     |      equivalent to the Twist2. This is the exponentiation of the twist vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> S = Twist2.Prismatic([1,2])
     |          >>> S.SE2()
     |
     |      :seealso: :func:`Twist3.exp`
     |
     |  __init__(self, arg=None, w=None, check=True)
     |          Construct a new 2D Twist object
     |
     |          :type a: 2-element array-like
     |          :return: 2D prismatic twist
     |          :rtype: Twist2 instance
     |
     |          - ``Twist2(R)`` is a 2D Twist object representing the SO(2) rotation expressed as
     |            a 2x2 matrix.
     |          - ``Twist2(T)`` is a 2D Twist object representing the SE(2) rigid-body motion expressed as
     |            a 3x3 matrix.
     |          - ``Twist2(X)`` if X is an SO2 instance then create a 2D Twist object representing the SO(2) rotation,
     |            and if X is an SE2 instance then create a 2D Twist object representing the SE(2) motion
     |          - ``Twist2(V)`` is a  2D Twist object specified directly by a 3-element array-like comprising the
     |            moment vector (1 element) and direction vector (2 elements).
     |
     |      :References:
     |          - Robotics, Vision & Control for Python, Section 2.2.2.4, P. Corke, Springer 2023.
     |          - Modern Robotics, Lynch & Park, Cambridge 2017
     |
     |      .. note:: Compared to Lynch & Park this module implements twist vectors
     |          with the translational components first, followed by rotational
     |          components, ie. :math:`[\omega, \vec{v}]`.
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator
     |
     |      :arg left: left multiplicand
     |      :arg right: right multiplicand
     |      :return: product
     |      :raises: ValueError
     |
     |      - ``X * Y`` compounds the twists ``X`` and ``Y``
     |      - ``X * s`` performs elementwise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
     |
     |      ========  ====================  ===================  ========================
     |           Multiplicands                   Product
     |      ------------------------------  ---------------------------------------------
     |         left      right                 type                 operation
     |      ========  ====================  ===================  ========================
     |      Twist2    Twist2                Twist2               product of exponentials
     |      Twist2    scalar                Twist2               element-wise product
     |      scalar    Twist2                Twist2               element-wise product
     |      Twist2    SE2                   Twist2               exponential x SE2
     |      ========  ====================  ===================  ========================
     |
     |      .. note::
     |
     |          #. scalar x Twist is handled by ``__rmul__``
     |          #. scalar multiplication is commutative but the result is not a group
     |          operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition the ``left`` and ``right`` operands may be a sequence
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __repr__(self)
     |      Readable representation of 2D twist
     |
     |      :return: readable representation of a twist as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> x = Twist2([1,2,3])
     |          >>> x
     |          >>> a.append(a)
     |          >>> a
     |
     |  __str__(self)
     |      Pretty string representation of 2D twist
     |
     |      :return: readable representation of the twist
     |      :rtype: str
     |
     |      Convert the twist's value to an array of numbers.
     |
     |      Example:
     |
     |      .. runblock: pycon
     |
     |          >>> x = Twist2([1,2,3])
     |          >>> print(x)
     |
     |  exp(self, theta=1, unit='rad')
     |      Exponentiate a 2D twist
     |
     |      :param theta: rotation magnitude, defaults to None
     |      :type theta: float, optional
     |      :param unit: rotational units, defaults to 'rad'
     |      :type unit: str, optional
     |      :return: SE(2) matrix
     |      :rtype: SE2 instance
     |
     |      - ``X.exp()`` is the homogeneous transformation equivalent to the twist,
     |        :math:`e^{[S]}`
     |      - ``X.exp(θ) as above but with a rotation of ``θ`` about the twist axis,
     |        :math:`e^{\theta[S]}`
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE2, Twist2
     |          >>> T = SE2(1, 2, 0.3)
     |          >>> S = Twist2(T)
     |          >>> S.exp(0)
     |          >>> S.exp(1)
     |
     |      .. note::
     |
     |          - For the second form, the twist must, if rotational, have a unit
     |            rotational component.
     |
     |      :seealso: :func:`spatialmath.smb.trexp2`
     |
     |  printline(self, **kwargs)
     |
     |  skewa(self)
     |      Convert 2D twist to se(2)
     |
     |      :return: An se(2) matrix
     |      :rtype: ndarray(3,3)
     |
     |      ``X.skewa()`` is the twist as a 3x3 augmented skew-symmetric matrix
     |      belonging to the group se(2). This is the Lie algebra of the
     |      corresponding SE(2) element.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2, base
     |          >>> S = Twist2([1,2,3])
     |          >>> se = S.skewa()
     |          >>> se
     |          >>> smb.trexp2(se)
     |
     |  unit(self)
     |      Unit twist
     |
     |      - ``S.unit()`` is a Twist2 object representing a unit twist aligned with the
     |        Twist ``S``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE2(1, 2, 0.3)
     |          >>> S = Twist2(T)
     |          >>> S.unit()
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  Tx(x)
     |      Create a new 2D twist for pure translation along the X-axis
     |
     |      :param x: translation distance along the X-axis
     |      :type x: float
     |      :return: 2D twist vector
     |      :rtype: Twist2 instance
     |
     |      `Twist2.Tx(x)` is an se(2) translation of ``x`` along the x-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> Twist2.Tx(2)
     |          >>> Twist2.Tx([2,3])
     |
     |
     |      :seealso: :func:`~spatialmath.smb.transforms2d.transl2`
     |      :SymPy: supported
     |
     |  Ty(y)
     |      Create a new 2D twist for pure translation along the Y-axis
     |
     |      :param y: translation distance along the Y-axis
     |      :type y: float
     |      :return: 2D twist vector
     |      :rtype: Twist2 instance
     |
     |      `Twist2.Ty(y) is an se(2) translation of ``y`` along the y-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> Twist2.Ty(2)
     |          >>> Twist2.Ty([2, 3])
     |
     |
     |      :seealso: :func:`~spatialmath.smb.transforms2d.transl2`
     |      :SymPy: supported
     |
     |  UnitPrismatic(a)
     |      Construct a new 2D primsmatic unit twist
     |
     |      :param a: Displacment
     |      :type a: array-like(2)
     |      :return: 2D prismatic twist
     |      :rtype: Twist2 instance
     |
     |      - ``Twist2.Prismatic(a)`` is a 2D Twist object representing 2D-translation in the direction ``a``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> Twist2.Prismatic([1, 2])
     |
     |  UnitRevolute(q)
     |      Construct a new 2D revolute unit twist
     |
     |      :param q: Point on the line of action
     |      :type q: array_like(2)
     |      :return: 2D prismatic twist
     |      :rtype: Twist2 instance
     |
     |      - ``Twist2.Revolute(q)`` is a 2D Twist object representing rotation about the 2D point ``q``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> Twist2.Revolute([0, 1])
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(v, check=True)
     |      Test if matrix is valid twist
     |
     |      :param x: array to test
     |      :type x: ndarray
     |      :return: Whether the value is a 3-vector or a valid 3x3 se(2) element
     |      :rtype: bool
     |
     |      A twist can be represented by a 6-vector or a 4x4 skew symmetric matrix,
     |      for example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2, base
     |          >>> import numpy as np
     |          >>> Twist2.isvalid([1, 2, 3])
     |          >>> a = smb.skewa([1, 2, 3])
     |          >>> a
     |          >>> Twist2.isvalid(a)
     |          >>> Twist2.isvalid(np.random.rand(3,3))
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  N
     |      Dimension of the object's group
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 2 for ``Twist2`` and corresponds to the
     |      dimension of the space (2D in this case) to which these
     |      rigid-body motions apply.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> x = Twist2()
     |          >>> x.N
     |
     |  ad
     |      Twist2.ad Logarithm of adjoint
     |
     |      - ``S.ad()`` is the logarithm of the adjoint matrix of the corresponding
     |        homogeneous transformation.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE2(1, 2, 0.3)
     |          >>> S = Twist2(T)
     |          >>> S.unit()
     |
     |      :seealso: SE3.Ad.
     |
     |  pole
     |      Pole of a 2D twist
     |
     |      :return: the pole of the twist
     |      :rtype: ndarray(2)
     |
     |      ``X.pole()`` is a point on the twist axis. For a pure translation
     |      this point is at infinity.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE2(1, 2, 0.3)
     |          >>> S = Twist2(T)
     |          >>> S.pole()
     |
     |  shape
     |      Shape of the object's interal array representation
     |
     |      :return: (3,)
     |      :rtype: tuple
     |
     |  v
     |      Moment vector of twist
     |
     |      :return: Moment vector
     |      :rtype: ndarray(2)
     |
     |      ``X.v`` is a 2-vector representing the moment vector of the twist.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> t = Twist2([1, 2, 3])
     |          >>> t.v
     |
     |  w
     |      Direction vector of twist
     |
     |      :return: Direction vector
     |      :rtype: float
     |
     |      ``X.w`` is a scalar representing the direction "vector" of the twist.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> t = Twist2([1, 2, 3])
     |          >>> t.w
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from BaseTwist:
     |
     |  __eq__(left, right)
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      ``S1 == S2`` is True if ``S1` is elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 == S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 == S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :rtype: bool
     |
     |      ``S1 == S2`` is True if ``S1` is not elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 != S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 != S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __truediv__(left, right)
     |
     |  inv(self)
     |      Inverse of Twist (superclass method)
     |
     |      :return: inverse
     |      :rtype: Twist instance
     |
     |      Compute the inverse of each of the values within the twist instance.
     |      The inverse is the negative of the twist vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3(SE3.Rand())
     |          >>> S
     |          >>> S.inv()
     |          >>> S * S.inv()
     |
     |  prod(self)
     |      Product of twists (superclass method)
     |
     |      :return: Product of elements
     |      :rtype: Twist2 or Twist3
     |
     |      For a twist instance with N values return the matrix product of those
     |      elements :math:`\prod_i=0^{N-1} S_i`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx([0.2, 0.3, 0.4])
     |          >>> len(S)
     |          >>> S.prod()
     |          >>> Twist3.Rx(0.9)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from BaseTwist:
     |
     |  S
     |      Twist as a vector (superclass property)
     |
     |      :return: Twist vector
     |      :rtype: ndarray(N)
     |
     |      - ``X.S`` is a 3-vector if X is a ``Twist2`` instance, and a 6-vector if
     |        X is a ``Twist3`` instance.
     |
     |      .. note::
     |
     |          - the vector is the unique elements of the se(N) representation.
     |          - the vector is sometimes referred to as the twist coordinate vector.
     |          - if ``len(X)`` > 1 then return a list of vectors.
     |
     |  isprismatic
     |      Test for prismatic twist (superclass property)
     |
     |      :return: Whether twist is purely prismatic
     |      :rtype: bool
     |
     |      A prismatic twist has :math:`\vec{\omega} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isprismatic
     |          >>> x = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> x.isprismatic
     |
     |  isrevolute
     |      Test for revolute twist (superclass property)
     |
     |      :return: Whether twist is purely revolute
     |      :rtype: bool
     |
     |      A revolute twist has :math:`\vec{v} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isrevolute
     |          >>> x = Twist3.UnitRevolute([1,2,3], [0,0,0])
     |          >>> x.isrevolute
     |
     |  isunit
     |      Test for unit twist (superclass property)
     |
     |      :return: Whether twist is a unit-twist
     |      :rtype: bool
     |
     |      A unit twist is one with a norm of 1, ie. :math:`\| S \| = 1`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3([1,2,3,4,5,6])
     |          >>> S.isunit()
     |          >>> S = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> S.isunit()
     |
     |  theta
     |      Twist angle (superclass method)
     |
     |      :return: magnitude of rotation (1x1) about the twist axis in radians
     |      :rtype: float
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from BaseTwist:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  __rmul__ = __mul__(self, n)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

    class Twist3(BaseTwist)
     |  Twist3(arg=None, w=None, check=True)
     |
     |  3D twist class
     |
     |  A Twist class holds the parameters of a twist, a representation of a
     |  3D rigid body transformation which is the unique elements of the Lie
     |  algebra se(3) of the corresponding SE(3) matrix.
     |
     |  :References:
     |      - Robotics, Vision & Control for Python, Section 2.3.2.3, P. Corke, Springer 2023.
     |      - Modern Robotics, Lynch & Park, Cambridge 2017
     |
     |  .. note:: Compared to Lynch & Park this module implements twist vectors
     |      with the translational components first, followed by rotational
     |      components, ie. :math:`[\omega, \vec{v}]`.
     |
     |  Method resolution order:
     |      Twist3
     |      BaseTwist
     |      spatialmath.baseposelist.BasePoseList
     |      collections.UserList
     |      collections.abc.MutableSequence
     |      collections.abc.Sequence
     |      collections.abc.Reversible
     |      collections.abc.Collection
     |      collections.abc.Sized
     |      collections.abc.Iterable
     |      collections.abc.Container
     |      abc.ABC
     |      builtins.object
     |
     |  Methods defined here:
     |
     |  Ad(self)
     |      Adjoint of 3D twist
     |
     |      :return: adjoint matrix
     |      :rtype: ndarray(6,6)
     |
     |      ``S.Ad()`` is the 6x6 adjoint matrix of the corresponding
     |      homogeneous transformation.
     |
     |      For a twist representing motion from frame {B} to {A}, the adjoint will
     |      transform a twist relative to frame {A} to one relative to frame {B}.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx(0.3)
     |          >>> S.Ad()
     |
     |      .. note:: This method computes the equivalent SE(3) matrix, then the adjoint
     |          of that.
     |
     |      :seealso: :func:`Twist3.ad`, :func:`Twist3.SE3`, :func:`Twist3.exp`
     |
     |  SE3(self, theta=1, unit='rad')
     |      Convert 3D twist to SE(3) matrix
     |
     |      :return: an SE(3) representation
     |      :rtype: SE3 instance
     |
     |      ``S.SE3()`` is an SE3 object representing the homogeneous transformation
     |      equivalent to the Twist3. This is the exponentiation of the twist vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx(0.3)
     |          >>> S.SE3()
     |
     |      :seealso: :func:`Twist3.exp`
     |
     |  __init__(self, arg=None, w=None, check=True)
     |      Construct a new 3D twist object
     |
     |      - ``Twist3()`` is a Twist3 instance representing null motion -- the
     |        identity twist
     |      - ``Twist3(S)`` is a Twist3 instance from an array-like (6,)
     |      - ``Twist3(v, w)`` is a Twist3 instance from a moment ``v`` (3,) and
     |        direction ``w`` (3,)
     |      - ``Twist3([S1, S2, ... SN])`` where each ``Si`` is a numpy array (6,)
     |      - ``Twist3(X)`` is a Twist3 instance with the same value as ``X``, ie.
     |        a copy
     |      - ``Twist3([X1, X2, ... XN])`` where each Xi is a Twist3 instance, is a
     |        Twist3 instance containing N motions
     |
     |  __mul__(left, right)
     |      Overloaded ``*`` operator
     |
     |      :arg left: left multiplicand
     |      :arg right: right multiplicand
     |      :return: product
     |      :raises: ValueError
     |
     |      Twist composition or scaling:
     |
     |      - ``X * Y`` compounds the twists ``X`` and ``Y``
     |      - ``X * s`` performs elementwise multiplication of the elements of ``X`` by ``s``
     |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
     |
     |      ========  ====================  ===================  ========================
     |           Multiplicands                   Product
     |      ------------------------------  ---------------------------------------------
     |         left      right                 type                 operation
     |      ========  ====================  ===================  ========================
     |      Twist3    Twist3                Twist3               product of exponentials
     |      Twist3    scalar                Twist3               element-wise product
     |      scalar    Twist3                Twist3               element-wise product
     |      Twist3    SE3                   Twist3               exponential x SE3
     |      ========  ====================  ===================  ========================
     |
     |      .. note::
     |
     |          #. scalar x Twist is handled by ``__rmul__``
     |          #. scalar multiplication is commutative but the result is not a group
     |          operation so the result will be a matrix
     |          #. Any other input combinations result in a ValueError.
     |
     |      For pose composition the ``left`` and ``right`` operands may be a sequence
     |
     |      =========   ==========   ====  ================================
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ================================
     |       1          1             1    ``prod = left * right``
     |       1          M             M    ``prod[i] = left * right[i]``
     |       N          1             M    ``prod[i] = left[i] * right``
     |       M          M             M    ``prod[i] = left[i] * right[i]``
     |      =========   ==========   ====  ================================
     |
     |  __repr__(self)
     |      Readable representation of 3D twist
     |
     |      :return: readable representation of a twist as a list of arrays
     |      :rtype: str
     |
     |      Example:
     |
     |      .. runblock: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.R([1,2,3], [4,5,6])
     |          >>> x
     |          >>> a.append(a)
     |          >>> a
     |
     |  __rmul__(right, left)
     |      Overloaded ``*`` operator
     |
     |      :arg right: right multiplicand
     |      :arg left: left multiplicand
     |      :return: product
     |      :raises: NotImplemented
     |
     |      Left-multiplication by a scalar
     |
     |      - ``s * X`` performs elementwise multiplication of the elements of ``X`` by ``s``
     |
     |  __str__(self)
     |      Pretty string representation of 3D twist
     |
     |      :return: readable representation of the twist
     |      :rtype: str
     |
     |      Convert the twist's value to an array of numbers.
     |
     |      Example:
     |
     |      .. runblock: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.R([1,2,3], [4,5,6])
     |          >>> print(x)
     |
     |  ad(self)
     |      Logarithm of adjoint of 3D twist
     |
     |      :return: logarithm of adjoint matrix
     |      :rtype: ndarray(6,6)
     |
     |      ``S.ad()`` is the 6x6 logarithm of the adjoint matrix of the
     |      corresponding homogeneous transformation.
     |
     |      For a twist representing motion from frame {B} to {A}, the adjoint will
     |      transform a twist relative to frame {A} to one relative to frame {B}.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx(0.3)
     |          >>> S.ad()
     |
     |      .. note:: An alternative approach to computing the adjoint is to exponentiate this 6x6
     |          matrix.
     |
     |      :seealso: :func:`Twist3.Ad`
     |
     |  exp(self, theta=1, unit='rad')
     |      Exponentiate a 3D twist
     |
     |      :param theta: rotation magnitude, defaults to None
     |      :type theta: float, optional
     |      :param units: rotational units, defaults to 'rad'
     |      :type units: str, optional
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      - ``X.exp()`` is the homogeneous transformation equivalent to the twist,
     |        :math:`e^{[S]}`
     |      - ``X.exp(θ) as above but with a rotation of ``θ`` about the twist axis,
     |        :math:`e^{    heta[S]}`
     |
     |      If ``len(X)==1`` and ``len(θ)==N`` then the resulting SE3 object has
     |      ``N`` values equivalent to the twist :math:`e^{ heta_i[S]}`.
     |
     |      If ``len(X)==N`` and ``len(θ)==1`` then the resulting SE3 object has
     |      ``N`` values equivalent to the twist :math:`e^{ heta[S_i]}`.
     |
     |      If ``len(X)==N`` and ``len(θ)==N`` then the resulting SE3 object has
     |      ``N`` values equivalent to the twist :math:`e^{ heta_i[S_i]}`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
     |          >>> S = Twist3(T)
     |          >>> S.exp(0)
     |          >>> S.exp(1)
     |
     |      .. note::
     |
     |          - For the second form, the twist must, if rotational, have a unit
     |            rotational component.
     |
     |      :seealso: :func:`spatialmath.smb.trexp`
     |
     |  line(self)
     |      Line of action of 3D twist as a Plucker line
     |
     |      :return: the 3D line of action
     |      :rtype: Line instance
     |
     |      ``X.line()`` is a Plucker object representing the line of the twist axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
     |          >>> S = Twist3(T)
     |          >>> S.line()
     |
     |  printline(self, **kwargs)
     |
     |  skewa(self)
     |      Convert 3D twist to se(3)
     |
     |      :return: An se(3) matrix
     |      :rtype: ndarray(4,4)
     |
     |      ``X.skewa()`` is the twist as a 4x4 augmented skew-symmetric matrix
     |      belonging to the group se(3). This is the Lie algebra of the
     |      corresponding SE(3) element.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3, base
     |          >>> S = Twist3.Rx(0.3)
     |          >>> se = S.skewa()
     |          >>> se
     |          >>> smb.trexp(se)
     |
     |  unit(self)
     |      Unit twist
     |
     |      - ``S.unit()`` is a Twist2 objec3 representing a unit twist aligned with the
     |        Twist ``S``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE3(1, 2, 0.3)
     |          >>> S = Twist3(T)
     |          >>> S.unit()
     |
     |  ----------------------------------------------------------------------
     |  Class methods defined here:
     |
     |  RPY(*pos, **kwargs)
     |      Create a new 3D twist from roll-pitch-yaw angles
     |
     |      :param 𝚪: roll-pitch-yaw angles
     |      :type 𝚪: array_like or numpy.ndarray with shape=(N,3)
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :param order: rotation order: 'zyx' [default], 'xyz', or 'yxz'
     |      :type order: str
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      - ``Twist3.RPY(𝚪)`` is a 3D rotation defined by a 3-vector of roll,
     |        pitch, yaw angles :math:`\Gamma=(r, p, y)` which correspond to
     |        successive rotations about the axes specified by ``order``:
     |
     |          - ``'zyx'`` [default], rotate by yaw about the z-axis, then by pitch about the new y-axis,
     |            then by roll about the new x-axis.  This is the **convention** for a mobile robot with x-axis forward
     |            and y-axis sideways.
     |          - ``'xyz'``, rotate by yaw about the x-axis, then by pitch about the new y-axis,
     |            then by roll about the new z-axis. This is the **convention** for a robot gripper with z-axis forward
     |            and y-axis between the gripper fingers.
     |          - ``'yxz'``, rotate by yaw about the y-axis, then by pitch about the new x-axis,
     |            then by roll about the new z-axis. This is the **convention** for a camera with z-axis parallel
     |            to the optical axis and x-axis parallel to the pixel rows.
     |
     |      If ``𝚪`` is an Nx3 matrix then the result is a sequence of rotations each defined by RPY angles
     |      corresponding to the rows of ``𝚪``.
     |
     |      - ``Twist3.RPY(⍺, β, 𝛾)`` as above but the angles are provided as three
     |        scalars.
     |
     |      Foo bar!
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.RPY(0.1, 0.2, 0.3)
     |          >>> Twist3.RPY([0.1, 0.2, 0.3])
     |          >>> Twist3.RPY(0.1, 0.2, 0.3, order='xyz')
     |          >>> Twist3.RPY(10, 20, 30, unit='deg')
     |
     |      :seealso: :meth:`~spatialmath.SE3.RPY`
     |      :SymPy: supported
     |
     |  Rand(*, xrange=(-1, 1), yrange=(-1, 1), zrange=(-1, 1), N=1)
     |      Create a new random 3D twist
     |
     |      :param xrange: x-axis range [min,max], defaults to [-1, 1]
     |      :type xrange: 2-element sequence, optional
     |      :param yrange: y-axis range [min,max], defaults to [-1, 1]
     |      :type yrange: 2-element sequence, optional
     |      :param zrange: z-axis range [min,max], defaults to [-1, 1]
     |      :type zrange: 2-element sequence, optional
     |      :param N: number of random transforms
     |      :type N: int
     |      :return: SE(3) matrix
     |      :rtype: SE3 instance
     |
     |      Return an SE3 instance with random rotation and translation.
     |
     |      - ``SE3.Rand()`` is a random SE(3) translation.
     |      - ``SE3.Rand(N=N)`` is an SE3 object containing a sequence of N random
     |        poses.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Rand(N=2)
     |
     |      :seealso: :func:`~spatialmath.quaternions.UnitQuaternion.Rand`
     |
     |  Rx(theta, unit='rad')
     |      Create a new 3D twist for pure rotation about the X-axis
     |
     |      :param θ: rotation angle about X-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      - ``Twist3.Rx(θ)`` is an SE(3) rotation of θ radians about the x-axis
     |      - ``Twist3.Rx(θ, "deg")`` as above but θ is in degrees
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Rx(0.3)
     |          >>> Twist3.Rx([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.trotx`
     |      :SymPy: supported
     |
     |  Ry(theta, unit='rad', t=None)
     |      Create a new 3D twist for pure rotation about the Y-axis
     |
     |      :param θ: rotation angle about X-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      - ``Twist3.Ry(θ)`` is an SO(3) rotation of θ radians about the y-axis
     |      - ``Twist3.Ry(θ, "deg")`` as above but θ is in degrees
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Ry(0.3)
     |          >>> Twist3.Ry([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.troty`
     |      :SymPy: supported
     |
     |  Rz(theta, unit='rad', t=None)
     |      Create a new 3D twist for pure rotation about the Z-axis
     |
     |      :param θ: rotation angle about Z-axis
     |      :type θ: float
     |      :param unit: angular units: 'rad' [default], or 'deg'
     |      :type unit: str
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      - ``Twist3.Rz(θ)`` is an SO(3) rotation of θ radians about the z-axis
     |      - ``Twist3.Rz(θ, "deg")`` as above but θ is in degrees
     |
     |      If ``θ`` is an array then the result is a sequence of rotations defined
     |      by consecutive elements.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Rz(0.3)
     |          >>> Twist3.Rz([0.3, 0.4])
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.trotz`
     |      :SymPy: supported
     |
     |  Tx(x)
     |      Create a new 3D twist for pure translation along the X-axis
     |
     |      :param x: translation distance along the X-axis
     |      :type x: float
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      ``Twist3.Tx(x)`` is an se(3) translation of ``x`` along the x-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Tx(2)
     |          >>> Twist3.Tx([2,3])
     |
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Ty(y)
     |      Create a new 3D twist for pure translation along the Y-axis
     |
     |      :param y: translation distance along the Y-axis
     |      :type y: float
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      ``Twist3.Ty(y)`` is an se(3) translation of ``y`` along the y-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Ty(2)
     |          >>> Twist3.Ty([2, 3])
     |
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
     |      :SymPy: supported
     |
     |  Tz(z)
     |      Create a new 3D twist for pure translation along the Z-axis
     |
     |      :param z: translation distance along the Z-axis
     |      :type z: float
     |      :return: 3D twist vector
     |      :rtype: Twist3 instance
     |
     |      ``Twist3.Tz(z)`` is an se(3) translation of ``z`` along the z-axis
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Tz(2)
     |          >>> Twist3.Tz([2, 3])
     |
     |      :seealso: :func:`~spatialmath.smb.transforms3d.transl`
     |      :SymPy: supported
     |
     |  UnitPrismatic(a)
     |      Construct a new 3D unit prismatic twist
     |
     |      :param a: Twist axis or line of action
     |      :type a: array_like(3)
     |      :return: a prismatic twist
     |      :rtype: Twist instance
     |
     |      A prismatic twist with a line of action in the z-direction would be:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Prismatic([0, 0, 1])
     |
     |  UnitRevolute(a, q, pitch=None)
     |      Construct a new 3D rotational unit twist
     |
     |      :param a: Twist axis or line of action
     |      :type a: array_like(3)
     |      :param q: Point on the line of action
     |      :type q: array_like(3)
     |      :param p: pitch, defaults to None
     |      :type p: float, optional
     |      :return: a rotational or helical twist
     |      :rtype: Twist instance
     |
     |      A revolute twist with a line of action in the z-direction and passing
     |      through (1, 2, 0) would be:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> Twist3.Revolute([0, 0, 1], [1, 2, 0])
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  isvalid(v, check=True)
     |      Test if matrix is valid twist
     |
     |      :param x: array to test
     |      :type x: ndarray
     |      :return: Whether the value is a 6-vector or a valid 4x4 se(3) element
     |      :rtype: bool
     |
     |      A twist can be represented by a 6-vector or a 4x4 skew symmetric matrix,
     |      for example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> from spatialmath.base import skewa
     |          >>> import numpy as np
     |          >>> Twist3.isvalid([1, 2, 3, 4, 5, 6])
     |          >>> a = skewa([1, 2, 3, 4, 5, 6])
     |          >>> a
     |          >>> Twist3.isvalid(a)
     |          >>> Twist3.isvalid(np.random.rand(4,4))
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties defined here:
     |
     |  N
     |      Dimension of the object's group
     |
     |      :return: dimension
     |      :rtype: int
     |
     |      Dimension of the group is 3 for ``Twist3`` and corresponds to the
     |      dimension of the space (3D in this case) to which these
     |      rigid-body motions apply.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3()
     |          >>> x.N
     |
     |  pitch
     |      Pitch of a 3D twist
     |
     |      :return: the pitch of the twist
     |      :rtype: float
     |
     |      ``X.pitch()`` is the pitch of the twist as a scalar in units of distance
     |      per radian.
     |
     |      If we consider the twist as a screw, this is the distance of
     |      translation along the screw axis for a one radian rotation about the
     |      screw axis.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
     |          >>> S = Twist3(T)
     |          >>> S.pitch
     |
     |  pole
     |      Pole of a 3D twist
     |
     |      :return: the pole of the twist
     |      :rtype: ndarray(3)
     |
     |      ``X.pole()`` is a point on the twist axis. For a pure translation
     |      this point is at infinity.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import SE3, Twist3
     |          >>> T = SE3(1, 2, 3) * SE3.Rx(0.3)
     |          >>> S = Twist3(T)
     |          >>> S.pole
     |
     |  shape
     |      Shape of the object's internal array representation
     |
     |      :return: (6,)
     |      :rtype: tuple
     |
     |  v
     |      Moment vector of twist
     |
     |      :return: Moment vector
     |      :rtype: ndarray(3)
     |
     |      ``X.v`` is a 3-vector representing the moment vector of the twist.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> t = Twist3([1, 2, 3, 4, 5, 6])
     |          >>> t.v
     |
     |  w
     |      Direction vector of twist
     |
     |      :return: Direction vector
     |      :rtype: ndarray(3)
     |
     |      ``X.w`` is a 3-vector representing the direction vector of the twist.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> t = Twist3([1, 2, 3, 4, 5, 6])
     |          >>> t.w
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes defined here:
     |
     |  __abstractmethods__ = frozenset()
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from BaseTwist:
     |
     |  __eq__(left, right)
     |      Overloaded ``==`` operator (superclass method)
     |
     |      :return: Equality of two operands
     |      :rtype: bool or list of bool
     |
     |      ``S1 == S2`` is True if ``S1` is elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist2
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 == S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 == S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __ne__(left, right)
     |      Overloaded ``!=`` operator (superclass method)
     |
     |      :rtype: bool
     |
     |      ``S1 == S2`` is True if ``S1` is not elementwise equal to ``S2``.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S1 = Twist3([1,2,3,4,5,6])
     |          >>> S2 = Twist3([1,2,3,4,5,6])
     |          >>> S1 != S2
     |          >>> S2 = Twist3([1,2,3,4,5,7])
     |          >>> S1 != S2
     |
     |      :seealso: :func:`__ne__`
     |
     |  __truediv__(left, right)
     |
     |  inv(self)
     |      Inverse of Twist (superclass method)
     |
     |      :return: inverse
     |      :rtype: Twist instance
     |
     |      Compute the inverse of each of the values within the twist instance.
     |      The inverse is the negative of the twist vector.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3(SE3.Rand())
     |          >>> S
     |          >>> S.inv()
     |          >>> S * S.inv()
     |
     |  prod(self)
     |      Product of twists (superclass method)
     |
     |      :return: Product of elements
     |      :rtype: Twist2 or Twist3
     |
     |      For a twist instance with N values return the matrix product of those
     |      elements :math:`\prod_i=0^{N-1} S_i`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3.Rx([0.2, 0.3, 0.4])
     |          >>> len(S)
     |          >>> S.prod()
     |          >>> Twist3.Rx(0.9)
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from BaseTwist:
     |
     |  S
     |      Twist as a vector (superclass property)
     |
     |      :return: Twist vector
     |      :rtype: ndarray(N)
     |
     |      - ``X.S`` is a 3-vector if X is a ``Twist2`` instance, and a 6-vector if
     |        X is a ``Twist3`` instance.
     |
     |      .. note::
     |
     |          - the vector is the unique elements of the se(N) representation.
     |          - the vector is sometimes referred to as the twist coordinate vector.
     |          - if ``len(X)`` > 1 then return a list of vectors.
     |
     |  isprismatic
     |      Test for prismatic twist (superclass property)
     |
     |      :return: Whether twist is purely prismatic
     |      :rtype: bool
     |
     |      A prismatic twist has :math:`\vec{\omega} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isprismatic
     |          >>> x = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> x.isprismatic
     |
     |  isrevolute
     |      Test for revolute twist (superclass property)
     |
     |      :return: Whether twist is purely revolute
     |      :rtype: bool
     |
     |      A revolute twist has :math:`\vec{v} = 0`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> x = Twist3.UnitPrismatic([1,2,3])
     |          >>> x.isrevolute
     |          >>> x = Twist3.UnitRevolute([1,2,3], [0,0,0])
     |          >>> x.isrevolute
     |
     |  isunit
     |      Test for unit twist (superclass property)
     |
     |      :return: Whether twist is a unit-twist
     |      :rtype: bool
     |
     |      A unit twist is one with a norm of 1, ie. :math:`\| S \| = 1`.
     |
     |      Example:
     |
     |      .. runblock:: pycon
     |
     |          >>> from spatialmath import Twist3
     |          >>> S = Twist3([1,2,3,4,5,6])
     |          >>> S.isunit()
     |          >>> S = Twist3.UnitRevolute([1,2,3], [4,5,6])
     |          >>> S.isunit()
     |
     |  theta
     |      Twist angle (superclass method)
     |
     |      :return: magnitude of rotation (1x1) about the twist axis in radians
     |      :rtype: float
     |
     |  ----------------------------------------------------------------------
     |  Data and other attributes inherited from BaseTwist:
     |
     |  __hash__ = None
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  __ge__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>=value.
     |
     |  __getitem__(self, i: 'Union[int, slice]') -> 'BasePoseList'
     |      Access value of an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to return
     |      :type i: int
     |      :return: the specific element of the pose
     |      :rtype: Quaternion or UnitQuaternion instance
     |      :raises IndexError: if the element is out of bounds
     |
     |      Note that only a single index is supported, slices are not.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x[1]
     |          >>> len(y)
     |          1
     |          >>> y = x[1:5]
     |          >>> len(y)
     |          4
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  __gt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self>value.
     |
     |  __le__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<=value.
     |
     |  __lt__(self, other: 'BasePoseList') -> 'Type[Exception]'
     |      Return self<value.
     |
     |  __setitem__(self, i: 'int', value: 'BasePoseList') -> 'None'
     |      Assign a value to an instance (BasePoseList superclass method)
     |
     |      :param i: index of element to assign to
     |      :type i: int
     |      :param value: the value to insert
     |      :type value: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of assigned value
     |
     |      Assign the argument to an element of the object's internal list of values.
     |      This supports the assignement operator, for example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x[3] = X()   # assign to position 3 in the list
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  append(self, item: 'BasePoseList') -> 'None'
     |      Append a value to an instance (BasePoseList superclass method)
     |
     |      :param x: the value to append
     |      :type x: Quaternion or UnitQuaternion instance
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  arghandler(self, arg: 'Any', convertfrom: 'Tuple' = (), check: 'Optional[bool]' = True) -> 'bool'
     |      Standard constructor support (BasePoseList superclass method)
     |
     |      :param arg: initial value
     |      :param convertfrom: list of classes to accept and convert from
     |      :type: tuple of typles
     |      :param check: check value is valid, defaults to True
     |      :type check: bool
     |      :raises ValueError: bad type passed
     |
     |      The value ``arg`` can be any of:
     |
     |      #. None, an identity value is created
     |      #. a numpy.ndarray of the appropriate shape and value which is valid for the subclass
     |      #. a list whose elements all meet the criteria above
     |      #. an instance of the subclass
     |      #. a list whose elements are all singelton instances of the subclass
     |
     |      For cases 2 and 3, a NumPy array or a list of NumPy array is passed.
     |      Each NumPyarray is tested for validity (if ``check`` is False a cursory
     |      check of shape is made, if ``check`` is True the numerical value is
     |      inspected) and converted to the required internal format by the
     |      ``_import`` method. The default ``_import`` method calls the ``isvalid``
     |      method for checking.  This mechanism allows equivalent forms to be
     |      passed, ie. 6x1 or 4x4 for an se(3).
     |
     |      If ``self`` is an instance of class ``A``, and an instance of class
     |      ``B`` is passed and ``B`` is an element of the ``convertfrom`` argument,
     |      then ``B.A()`` will be invoked to perform the type conversion.
     |
     |      Examples::
     |
     |          SE3()
     |          SE3(np.identity(4))
     |          SE3([np.identity(4), np.identity(4)])
     |          SE3(SE3())
     |          SE3([SE3(), SE3()])
     |          Twist3(SE3())
     |
     |  binop(self, right: 'BasePoseList', op: 'Callable', op2: 'Optional[Callable]' = None, list1: 'Optional[bool]' = True) -> 'List'
     |      Perform binary operation
     |
     |      :param left: left operand
     |      :type left: BasePoseList subclass
     |      :param right: right operand
     |      :type right: BasePoseList subclass, scalar or array
     |      :param op: binary operation
     |      :type op: callable
     |      :param op2: binary operation
     |      :type op2: callable
     |      :param list1: return single array as a list, default True
     |      :type list1: bool
     |      :raises ValueError: arguments are not compatible
     |      :return: list of values
     |      :rtype: list
     |
     |      The is a helper method for implementing binary operation with overloaded
     |      operators such as ``X * Y`` where ``X`` and ``Y`` are both subclasses
     |      of ``BasePoseList``.  Each operand has a list of one or more
     |      values and this methods computes a list of result values according to:
     |
     |      =========   ==========   ====  ===================================
     |            Inputs                    Output
     |      ----------------------   -----------------------------------------
     |      len(left)   len(right)   len     operation
     |      =========   ==========   ====  ===================================
     |       1          1             1    ``ret = op(left, right)``
     |       1          M             M    ``ret[i] = op(left, right[i])``
     |       M          1             M    ``ret[i] = op(left[i], right)``
     |       M          M             M    ``ret[i] = op(left[i], right[i])``
     |      =========   ==========   ====  ===================================
     |
     |      The arguments to ``op`` are the internal numeric values, ie. as returned
     |      by the ``._A`` property.
     |
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |      If the right operand is not a ``BasePoseList`` subclass, but is a numeric
     |      scalar or array then then ``op2`` is invoked
     |
     |      For example::
     |
     |          X._binop(Y, lambda x, y: x + y)
     |
     |      =========   ====  ===================================
     |        Input                    Output
     |      ---------   -----------------------------------------
     |      len(left)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op2(left, right)``
     |       M           M    ``ret[i] = op2(left[i], right)``
     |      =========   ====  ===================================
     |
     |      There is no check on the shape of ``right`` if it is an array.
     |      The result is always a list, except for the first case above and
     |      ``list1`` is ``False``.
     |
     |  extend(self, iterable: 'BasePoseList') -> 'None'
     |      Extend sequence of values in an instance (BasePoseList superclass method)
     |
     |      :param x: the value to extend
     |      :type x: instance of same type
     |      :raises ValueError: incorrect type of appended object
     |
     |      Appends the argument's values to the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.append(X.Alloc(5))   # extend the list
     |          >>> len(x)
     |          15
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  insert(self, i: 'int', item: 'BasePoseList') -> 'None'
     |      Insert a value to an instance (BasePoseList superclass method)
     |
     |      :param i: element to insert value before
     |      :type i: int
     |      :param item: the value to insert
     |      :type item: instance of same type
     |      :raises ValueError: incorrect type of inserted value
     |
     |      Inserts the argument into the object's internal list of values.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> x.insert(0, X())   # insert at start of list
     |          >>> len(x)
     |          11
     |          >>> x.insert(10, X())   # append to the list
     |          >>> len(x)
     |          11
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |      .. note:: If ``i`` is beyond the end of the list, the item is appended
     |          to the list
     |
     |  pop(self, i: 'Optional[int]' = -1) -> 'Self'
     |      Pop value from an instance (BasePoseList superclass method)
     |
     |      :param i: item in the list to pop, default is last
     |      :type i: int
     |      :return: the popped value
     |      :rtype: instance of same type
     |      :raises IndexError: if there are no values to pop
     |
     |      Removes a value from the value list and returns it.  The original
     |      instance is modified.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |          >>> y = x.pop()  # pop the last value x[9]
     |          >>> len(x)
     |          9
     |          >>> y = x.pop(0)  # pop the first value x[0]
     |          >>> len(x)
     |          8
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  unop(self, op: 'Callable', matrix: 'Optional[bool]' = False) -> 'Union[NDArray, List]'
     |      Perform unary operation
     |
     |      :param self: operand
     |      :type self: BasePoseList subclass
     |      :param op: unnary operation
     |      :type op: callable
     |      :param matrix: return array instead of list, default False
     |      :type matrix: bool
     |      :return: operation results
     |      :rtype: list or NumPy array
     |
     |      The is a helper method for implementing unary operations where the
     |      operand has multiple value. This method computes the value of
     |      the operation for all input values and returns the result as either
     |      a list or as a matrix which vertically stacks the results.
     |
     |      =========   ====  ===================================
     |        Input                     Output
     |      ---------   -----------------------------------------
     |      len(self)   len     operation
     |      =========   ====  ===================================
     |       1           1    ``ret = op(self)``
     |       M           M    ``ret[i] = op(self[i])``
     |       M           M    ``ret[i,;] = op(self[i])``
     |      =========   ====  ===================================
     |
     |      The result is:
     |
     |      - a list of values if ``matrix==False``, or
     |      - a 2D NumPy stack of values if ``matrix==True``, it is assumed
     |        that the value is a 1D array.
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  Alloc(n: 'Optional[int]' = 1) -> 'Self'
     |      Construct an instance with N default values (BasePoseList superclass method)
     |
     |      :param n: Number of values, defaults to 1
     |      :type n: int, optional
     |      :return: pose instance with ``n`` default values
     |
     |      ``X.Alloc(N)`` creates an instance of the pose class ``X`` with ``N``
     |      default values, ie. ``len(X)`` will be ``N``.
     |
     |      ``X`` can be considered a vector of pose objects, and those elements
     |      can be referenced ``X[i]`` or assigned to ``X[i] = ...``.
     |
     |      .. note:: The default value depends on the pose class and is the result
     |                of the empty constructor. For ``SO2``,
     |                ``SE2``, ``SO3``, ``SE3`` it is an identity matrix, for a
     |                twist class ``Twist2`` or ``Twist3`` it is a zero vector,
     |                for a ``UnitQuaternion`` or ``Quaternion`` it is a zero
     |                vector.
     |
     |      Example::
     |
     |          >>> x = X.Alloc(10)
     |          >>> len(x)
     |          10
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  Empty() -> 'Self'
     |      Construct an empty instance (BasePoseList superclass method)
     |
     |      :return: pose instance with zero values
     |
     |      Example::
     |
     |          >>> x = X.Empty()
     |          >>> len(x)
     |          0
     |
     |      where ``X`` is any of the SMTB classes.
     |
     |  ----------------------------------------------------------------------
     |  Readonly properties inherited from spatialmath.baseposelist.BasePoseList:
     |
     |  A
     |      Array value of an instance (BasePoseList superclass method)
     |
     |      :return: NumPy array value of this instance
     |      :rtype: ndarray
     |
     |      - ``X.A`` is a NumPy array that represents the value of this instance,
     |        and has a shape given by ``X.shape``.
     |
     |      .. note:: This assumes that ``len(X)`` == 1, ie. it is a single-valued
     |          instance.
     |
     |  __array_interface__
     |      Copies the numpy array interface from the first numpy array
     |      so that C extenstions with this spatial math class have direct
     |      access to the underlying numpy array
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.UserList:
     |
     |  __add__(self, other)
     |
     |  __contains__(self, item)
     |
     |  __copy__(self)
     |
     |  __delitem__(self, i)
     |
     |  __iadd__(self, other)
     |
     |  __imul__(self, n)
     |
     |  __len__(self)
     |
     |  __radd__(self, other)
     |
     |  clear(self)
     |      S.clear() -> None -- remove all items from S
     |
     |  copy(self)
     |
     |  count(self, item)
     |      S.count(value) -> integer -- return number of occurrences of value
     |
     |  index(self, item, *args)
     |      S.index(value, [start, [stop]]) -> integer -- return first index of value.
     |      Raises ValueError if the value is not present.
     |
     |      Supporting start and stop arguments is optional, but
     |      recommended.
     |
     |  remove(self, item)
     |      S.remove(value) -- remove first occurrence of value.
     |      Raise ValueError if the value is not present.
     |
     |  reverse(self)
     |      S.reverse() -- reverse *IN PLACE*
     |
     |  sort(self, /, *args, **kwds)
     |
     |  ----------------------------------------------------------------------
     |  Data descriptors inherited from collections.UserList:
     |
     |  __dict__
     |      dictionary for instance variables
     |
     |  __weakref__
     |      list of weak references to the object
     |
     |  ----------------------------------------------------------------------
     |  Methods inherited from collections.abc.Sequence:
     |
     |  __iter__(self)
     |
     |  __reversed__(self)
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Reversible:
     |
     |  __subclasshook__(C)
     |      Abstract classes can override this to customize issubclass().
     |
     |      This is invoked early on by abc.ABCMeta.__subclasscheck__().
     |      It should return True, False or NotImplemented.  If it returns
     |      NotImplemented, the normal algorithm is used.  Otherwise, it
     |      overrides the normal algorithm (and the outcome is cached).
     |
     |  ----------------------------------------------------------------------
     |  Class methods inherited from collections.abc.Iterable:
     |
     |  __class_getitem__ = GenericAlias(...)
     |      Represent a PEP 585 generic type
     |
     |      E.g. for t = list[int], t.__origin__ is list and t.__args__ is (int,).

FILE
    c:\users\youse\appdata\local\programs\python\python312\lib\site-packages\spatialmath\twist.py