diff --git a/docs/source/_templates/autosummary/method.rst b/docs/source/_templates/autosummary/method.rst index 819ffa497..9abaeec7f 100644 --- a/docs/source/_templates/autosummary/method.rst +++ b/docs/source/_templates/autosummary/method.rst @@ -1,7 +1,8 @@ :orphan: -{{ class + '.' + name | escape | underline}} +{{ (class + '.' + name) | escape | underline}} .. currentmodule:: {{ module }} .. auto{{ objtype }}:: {{ fullname }} + :no-index: diff --git a/docs/source/conf.py b/docs/source/conf.py index 64d12388b..c28456c07 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -170,7 +170,14 @@ # the documentation napoleon_include_special_with_doc = True -napoleon_custom_sections = ["Synopsis"] +# Napoleon is still needed: tools/urdf/utils.py and urdf.py have genuine +# NumPy-style docstrings (vendored/adapted from an external URDF library) +# that depend on it. Everywhere else uses explicit reST fields directly. +# Bare NumPy-style section headers (Note, Examples, See Also, ...) mixed +# into otherwise-reST docstrings should use explicit directives +# (.. rubric:: Notes, etc.) instead — Napoleon's heuristic recognition of +# those bare headers can conflict with sphinx_autodoc_typehints (see +# tech-debt.md, 2026-07-05). # -------- Options AutoSummary -------------------------------------------------------# @@ -187,11 +194,18 @@ # -------- Suppress common noisy warnings ----------------------------------------# # Suppress "more than one target found" for short/common attribute names like -# n, m, robot, symbolic that appear across many classes, and suppress duplicate -# object description warnings for classes documented both inline and in stubs. +# n, m, robot, symbolic that appear across many classes, and duplicate-citation +# warnings for references (e.g. Yoshikawa85) defined in both a narrative page +# and a docstring pulled in from two classes. +# +# Note: "duplicate object description" (autodoc members documented both +# inline and via a separate IK/stubs/ page) is a different warning class +# with no type/subtype tag at all, so it can't be suppressed here — it's +# fixed at the source instead, via :no-index: in +# _templates/autosummary/method.rst. suppress_warnings = [ "ref.python", # ambiguous cross-references (multiple targets for 'n', 'm', etc.) - "duplicate", # duplicate object descriptions (IKSolution, IKSolver defined twice) + "ref.citation", # duplicate citations (Yoshikawa85 etc in both arm_*.rst and docstrings) ] # -------- Options favicon -------------------------------------------------------# diff --git a/src/roboticstoolbox/blocks/arm.py b/src/roboticstoolbox/blocks/arm.py index 13a02d88c..9963b7d34 100644 --- a/src/roboticstoolbox/blocks/arm.py +++ b/src/roboticstoolbox/blocks/arm.py @@ -366,7 +366,6 @@ class ArmPlot(GraphicsBlock): - 0 - ndarray(N) - :math:`\mathit{q}`, joint configuration - * - Output Create a robot animation using the robot's ``plot`` method. diff --git a/src/roboticstoolbox/models/DH/Hyper.py b/src/roboticstoolbox/models/DH/Hyper.py index f96a3b8e5..1839b5f89 100644 --- a/src/roboticstoolbox/models/DH/Hyper.py +++ b/src/roboticstoolbox/models/DH/Hyper.py @@ -38,8 +38,8 @@ class Hyper(DHRobot): :References: - "A divide and conquer articulated-body algorithm for parallel O(log(n)) - calculation of rigid body dynamics, Part 2", - Int. J. Robotics Research, 18(9), pp 876-892. + calculation of rigid body dynamics, Part 2", + Int. J. Robotics Research, 18(9), pp 876-892. :seealso: :func:`Coil`, :func:`Ball` diff --git a/src/roboticstoolbox/models/DH/Hyper3d.py b/src/roboticstoolbox/models/DH/Hyper3d.py index 1c163cd7c..39605d433 100644 --- a/src/roboticstoolbox/models/DH/Hyper3d.py +++ b/src/roboticstoolbox/models/DH/Hyper3d.py @@ -38,8 +38,8 @@ class Hyper3d(DHRobot): :References: - "A divide and conquer articulated-body algorithm for parallel O(log(n)) - calculation of rigid body dynamics, Part 2", - Int. J. Robotics Research, 18(9), pp 876-892. + calculation of rigid body dynamics, Part 2", + Int. J. Robotics Research, 18(9), pp 876-892. :seealso: :func:`Coil`, :func:`Ball` diff --git a/src/roboticstoolbox/models/DH/Orion5.py b/src/roboticstoolbox/models/DH/Orion5.py index 37c09571c..114274d66 100755 --- a/src/roboticstoolbox/models/DH/Orion5.py +++ b/src/roboticstoolbox/models/DH/Orion5.py @@ -34,8 +34,8 @@ class Orion5(DHRobot): - Robot has only 4 DoF. :references: - - https://rawrobotics.com.au/orion5 - - https://drive.google.com/file/d/0B6_9_-ZgiRdTNkVqMEkxN2RSc2c/view + - ``https://rawrobotics.com.au/orion5`` + - ``https://drive.google.com/file/d/0B6_9_-ZgiRdTNkVqMEkxN2RSc2c/view`` .. codeauthor:: Aditya Dua .. codeauthor:: Peter Corke diff --git a/src/roboticstoolbox/models/ETS/Puma560.py b/src/roboticstoolbox/models/ETS/Puma560.py index ddb3ca462..5183b488b 100644 --- a/src/roboticstoolbox/models/ETS/Puma560.py +++ b/src/roboticstoolbox/models/ETS/Puma560.py @@ -15,10 +15,11 @@ class Puma560(Robot): - The model has different joint offset conventions compared to ``DH.Puma560()``. For this robot: - - Zero joint angles ``qz`` is the vertical configuration, - corresponding to ``qr`` with ``DH.Puma560()`` - - ``qbent`` is the bent configuration, corresponding to - ``qz`` with ``DH.Puma560()`` + + - Zero joint angles ``qz`` is the vertical configuration, + corresponding to ``qr`` with ``DH.Puma560()`` + - ``qbent`` is the bent configuration, corresponding to + ``qz`` with ``DH.Puma560()`` :references: - "A Simple and Systematic Approach to Assigning Denavit–Hartenberg diff --git a/src/roboticstoolbox/robot/BaseRobot.py b/src/roboticstoolbox/robot/BaseRobot.py index af76376c0..01ff118da 100644 --- a/src/roboticstoolbox/robot/BaseRobot.py +++ b/src/roboticstoolbox/robot/BaseRobot.py @@ -413,13 +413,16 @@ def __getitem__(self, i: int | str) -> LinkType: :param i: link number or name :returns: i'th link or named link + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> print(robot[1]) # print the 2nd link - >>> print([link.a for link in robot]) # print all the a_j values + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> print(robot[1]) # print the 2nd link + >>> print([link.a for link in robot]) # print all the a_j values .. rubric:: Notes @@ -573,12 +576,15 @@ def n(self) -> int: Number of joints :returns: Number of joints + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.n + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.n See Also -------- @@ -598,13 +604,15 @@ def nlinks(self): static links :returns: Number of links + Examples -------- .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.nlinks + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.nlinks See Also -------- @@ -624,13 +632,15 @@ def nbranches(self) -> int: zero children :returns: number of branches in the robot's kinematic tree + Examples -------- .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.ETS.Panda() - >>> robot.nbranches + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.ETS.Panda() + >>> robot.nbranches See Also -------- @@ -711,13 +721,15 @@ def hasdynamics(self): :returns: Robot has dynamic parameters :returns: At least one link has associated dynamic parameters. + Examples -------- .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.hasdynamics: + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.hasdynamics """ @@ -731,13 +743,15 @@ def hasgeometry(self): At least one link has associated mesh to describe its shape. :returns: Robot has geometry model + Examples -------- .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.hasgeometry + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.hasgeometry See Also -------- @@ -754,13 +768,15 @@ def hascollision(self): :returns: Robot has collision model :returns: At least one link has associated collision model. + Examples -------- .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.hascollision + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.hascollision See Also -------- @@ -883,12 +899,15 @@ def qlim(self) -> NDArray: :param qlim: An array of joints limits (2, n) :raises ValueError: unset limits for a prismatic joint :returns: Array of joint limit values + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.qlim + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.qlim """ @@ -941,14 +960,17 @@ def structure(self) -> str: joint, and ``P`` for a prismatic joint. :returns: joint configuration string + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.structure - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.structure + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.structure + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.structure .. rubric:: Notes @@ -974,14 +996,17 @@ def prismaticjoints(self) -> list[bool]: Revolute joints as bool array :returns: array of joint type, True if prismatic + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.prismaticjoints - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.prismaticjoints + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.prismaticjoints + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.prismaticjoints .. rubric:: Notes @@ -1003,14 +1028,17 @@ def revolutejoints(self) -> list[bool]: Revolute joints as bool array :returns: array of joint type, True if revolute + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.revolutejoints - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.revolutejoints + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.revolutejoints + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.revolutejoints .. rubric:: Notes @@ -1388,9 +1416,12 @@ def ets( :raises ValueError: a link does not belong to this ERobot :raises TypeError: a bad link argument :returns: elementary transform sequence + Examples -------- + .. runblock:: pycon + >>> import roboticstoolbox as rtb >>> panda = rtb.models.ETS.Panda() >>> panda.ets() @@ -1514,13 +1545,16 @@ def todegrees(self, q) -> NDArray: :returns: or prismatic joints, ie. prismatic joint values are not converted. :returns: If ``q`` is a matrix, with one column per joint, the conversion is :returns: performed columnwise. + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> from math import pi - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.todegrees([pi/4, pi/8, 2, -pi/4, pi/6, pi/3]) + + >>> import roboticstoolbox as rtb + >>> from math import pi + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.todegrees([pi/4, pi/8, 2, -pi/4, pi/6, pi/3]) """ @@ -1548,12 +1582,15 @@ def toradians(self, q) -> NDArray: :param q: The joint configuration of the robot :returns: a vector of joint coordinates in radians and metres + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.toradians([10, 20, 2, 30, 40, 50]) + + >>> import roboticstoolbox as rtb + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.toradians([10, 20, 2, 30, 40, 50]) """ @@ -1573,14 +1610,17 @@ def isrevolute(self, j) -> bool: Check if joint is revolute :returns: True if revolute + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.revolutejoints - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.isrevolute(1) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.revolutejoints + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.isrevolute(1) See Also -------- @@ -1595,14 +1635,17 @@ def isprismatic(self, j) -> bool: Check if joint is prismatic :returns: True if prismatic + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.prismaticjoints - >>> stanford = rtb.models.DH.Stanford() - >>> stanford.isprismatic(1) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.prismaticjoints + >>> stanford = rtb.models.DH.Stanford() + >>> stanford.isprismatic(1) See Also -------- @@ -1652,14 +1695,17 @@ def addconfiguration_attr(self, name: str, q: ArrayLike, unit: str = "rad"): :param name: Name of the joint configuration :param q: Joint configuration + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) - >>> robot.mypos - >>> robot.configs["mypos"] + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) + >>> robot.mypos + >>> robot.configs["mypos"] .. rubric:: Notes @@ -1688,13 +1734,16 @@ def addconfiguration(self, name: str, q: NDArray): :param name: Name of the joint configuration :param q: Joint configuration + Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) - >>> robot.configs["mypos"] + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.addconfiguration_attr("mypos", [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]) + >>> robot.configs["mypos"] See Also -------- @@ -1748,11 +1797,12 @@ def random_q(self): The value for each joint is uniform randomly distributed between the limits set for the robot. - Note - ---- + .. rubric:: Notes + The joint limit for all joints must be set. :returns: Random joint configuration :rtype: ndarray(n) + See Also -------- :func:`Robot.qlim` @@ -1770,8 +1820,10 @@ def hierarchy(self) -> None: Pretty print the robot link hierachy :returns: Pretty print of the robot model + Examples -------- + Makes a robot and prints the heirachy .. runblock:: pycon @@ -2069,19 +2121,14 @@ def teach( ``robot.teach()`` as above except the robot's stored value of ``q`` is used. - q - The joint configuration of the robot (Optional, + :param q: The joint configuration of the robot (Optional, if not supplied will use the stored q values). - block - Block operation of the code and keep the figure open - limits - Custom view limits for the plot. If not supplied will + :param block: Block operation of the code and keep the figure open + :param limits: Custom view limits for the plot. If not supplied will autoscale, [x1, x2, y1, y2, z1, z2] - vellipse - (Plot Option) Plot the velocity ellipse at the + :param vellipse: (Plot Option) Plot the velocity ellipse at the end-effector (this option is for 'pyplot' only) - fellipse - (Plot Option) Plot the force ellipse at the + :param fellipse: (Plot Option) Plot the force ellipse at the end-effector (this option is for 'pyplot' only) :returns: A reference to the PyPlot object which controls the matplotlib figure @@ -2089,14 +2136,15 @@ def teach( .. rubric:: Notes - Program execution is blocked until the teach window is - dismissed. If ``block=False`` the method is non-blocking but - you need to poll the window manager to ensure that the window - remains responsive. + dismissed. If ``block=False`` the method is non-blocking but + you need to poll the window manager to ensure that the window + remains responsive. - The slider limits are derived from the joint limit properties. - If not set then: - - For revolute joints they are assumed to be [-pi, +pi] - - For prismatic joint they are assumed unknown and an error - occurs. + If not set then: + + - For revolute joints they are assumed to be [-pi, +pi] + - For prismatic joint they are assumed unknown and an error + occurs. """ @@ -2175,8 +2223,10 @@ def showgraph(self, display_graph: bool = True, **kwargs) -> str | None: :param etsbox: Put the link ETS in a box, otherwise an edge label :param jtype: Arrowhead to node indicates revolute or prismatic type :param static: Show static joints in blue and bold + Examples -------- + >>> import roboticstoolbox as rtb >>> panda = rtb.models.URDF.Panda() >>> panda.showgraph() @@ -2221,35 +2271,39 @@ def dotfile( """ Write a link transform graph as a GraphViz dot file - The file can be processed using dot: + The file can be processed using dot:: + % dot -Tpng -o out.png dotfile.dot The nodes are: - - Base is shown as a grey square. This is the world frame origin, - but can be changed using the ``base`` attribute of the robot. - - Link frames are indicated by circles - - ETS transforms are indicated by rounded boxes + + - Base is shown as a grey square. This is the world frame origin, + but can be changed using the ``base`` attribute of the robot. + - Link frames are indicated by circles + - ETS transforms are indicated by rounded boxes The edges are: - - an arrow if `jtype` is False or the joint is fixed - - an arrow with a round head if `jtype` is True and the joint is - revolute - - an arrow with a box head if `jtype` is True and the joint is - prismatic + + - an arrow if `jtype` is False or the joint is fixed + - an arrow with a round head if `jtype` is True and the joint is + revolute + - an arrow with a box head if `jtype` is True and the joint is + prismatic Edge labels or nodes in blue have a fixed transformation to the preceding link. - Note - ---- + .. rubric:: Notes + If ``filename`` is a file object then the file will *not* - be closed after the GraphViz model is written. + be closed after the GraphViz model is written. :param file: Name of file to write to :param etsbox: Put the link ETS in a box, otherwise an edge label :param ets: Display the full ets with "full" or a brief version with "brief" :param jtype: Arrowhead to node indicates revolute or prismatic type :param static: Show static joints in blue and bold + See Also -------- :func:`showgraph` diff --git a/src/roboticstoolbox/robot/DHLink.py b/src/roboticstoolbox/robot/DHLink.py index 74ed198ea..d847d485c 100644 --- a/src/roboticstoolbox/robot/DHLink.py +++ b/src/roboticstoolbox/robot/DHLink.py @@ -724,6 +724,7 @@ class RevoluteDH(DHLink): The link transform is :math:`\underbrace{\mathbf{T}_{rz}(q_i)}_{\mbox{variable}} \cdot \mathbf{T}_{tz}(d_i) \cdot \mathbf{T}_{tx}(a_i) \cdot \mathbf{T}_{rx}(\alpha_i)` where :math:`q_i` is the joint variable. + :references: - Robotics, Vision & Control in Python, 3e, P. Corke, Springer 2023, Chap 7. @@ -779,12 +780,14 @@ class PrismaticDH(DHLink): :type Tc: ndarray(2,) :param G: dynamic - gear ratio :type G: float + A subclass of the DHLink class for a prismatic joint that holds all information related to a robot link such as kinematics parameters, rigid-body inertial parameters, motor and transmission parameters. The link transform is :math:`\mathbf{T}_{rz}(\theta_i) \cdot \underbrace{\mathbf{T}_{tz}(q_i)}_{\mbox{variable}} \cdot \mathbf{T}_{tx}(a_i) \cdot \mathbf{T}_{rx}(\alpha_i)` where :math:`q_i` is the joint variable. + :references: - Robotics, Vision & Control in Python, 3e, P. Corke, Springer 2023, Chap 7. diff --git a/src/roboticstoolbox/robot/DHRobot.py b/src/roboticstoolbox/robot/DHRobot.py index 43cc17d33..1ccacc679 100644 --- a/src/roboticstoolbox/robot/DHRobot.py +++ b/src/roboticstoolbox/robot/DHRobot.py @@ -1047,7 +1047,7 @@ def fkine_all(self, q=None, old=True): .. note:: - Old behaviour is to return a list of ``n`` frames {1} to {n}, but - if ``old=False`` it returns ``n``+1 frames {0} to {n}, ie. it + if ``old=False`` it returns ``n`` + 1 frames {0} to {n}, ie. it includes the base frame. - The robot's base or tool transform, if present, are incorporated into the result. @@ -1512,7 +1512,7 @@ def rne_python( .. note:: - This is a pure Python implementation and slower than the .rne() - which is written in C. + which is written in C. - This version supports symbolic model parameters - Verified against MATLAB code @@ -1970,15 +1970,15 @@ def ik_lm_chan( This method can be used for robots with any number of degrees of freedom. The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -2021,8 +2021,7 @@ def ik_lm_chan( .. note:: - - See `Toolbox kinematics wiki page - `_ + - See `Toolbox kinematics wiki page `_ - Implements a Levenberg-Marquadt variable-damping solver. - The tolerance is computed on the norm of the error between current and desired tool pose. This norm is computed from @@ -2075,15 +2074,15 @@ def ik_lm_wampler( This method can be used for robots with any number of degrees of freedom. The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -2126,8 +2125,7 @@ def ik_lm_wampler( .. note:: - - See `Toolbox kinematics wiki page - `_ + - See `Toolbox kinematics wiki page `_ - Implements a Levenberg-Marquadt variable-damping solver. - The tolerance is computed on the norm of the error between current and desired tool pose. This norm is computed from @@ -2180,15 +2178,15 @@ def ik_lm_sugihara( This method can be used for robots with any number of degrees of freedom. The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -2231,8 +2229,7 @@ def ik_lm_sugihara( .. note:: - - See `Toolbox kinematics wiki page - `_ + - See `Toolbox kinematics wiki page `_ - Implements a Levenberg-Marquadt variable-damping solver. - The tolerance is computed on the norm of the error between current and desired tool pose. This norm is computed from @@ -2286,15 +2283,15 @@ def ik_nr( This method can be used for robots with any number of degrees of freedom. The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -2337,8 +2334,7 @@ def ik_nr( .. note:: - - See `Toolbox kinematics wiki page - `_ + - See `Toolbox kinematics wiki page `_ - Implements a Levenberg-Marquadt variable-damping solver. - The tolerance is computed on the norm of the error between current and desired tool pose. This norm is computed from @@ -2394,15 +2390,15 @@ def ik_gn( This method can be used for robots with any number of degrees of freedom. The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -2445,8 +2441,7 @@ def ik_gn( .. note:: - - See `Toolbox kinematics wiki page - `_ + - See `Toolbox kinematics wiki page `_ - Implements a Levenberg-Marquadt variable-damping solver. - The tolerance is computed on the norm of the error between current and desired tool pose. This norm is computed from diff --git a/src/roboticstoolbox/robot/Dynamics.py b/src/roboticstoolbox/robot/Dynamics.py index f3b7bbba9..5d77422ab 100644 --- a/src/roboticstoolbox/robot/Dynamics.py +++ b/src/roboticstoolbox/robot/Dynamics.py @@ -39,10 +39,12 @@ def dynamics(self: RobotProto): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.dynamics() + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.dynamics() """ unicode = rtb_get_param("unicode") @@ -417,10 +419,12 @@ def accel(self: RobotProto, q, qd, torque, gravity=None): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.accel(puma.qz, 0.5 * np.ones(6), np.zeros(6)) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.accel(puma.qz, 0.5 * np.ones(6), np.zeros(6)) .. rubric:: Notes @@ -667,10 +671,12 @@ def inertia(self: RobotProto, q: NDArray) -> NDArray: Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.inertia(puma.qz) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.inertia(puma.qz) .. rubric:: Notes @@ -734,10 +740,12 @@ def coriolis(self: RobotProto, q, qd): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.coriolis(puma.qz, 0.5 * np.ones((6,))) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.coriolis(puma.qz, 0.5 * np.ones((6,))) .. rubric:: Notes @@ -828,10 +836,12 @@ def gravload( Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.gravload(puma.qz) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.gravload(puma.qz) """ @@ -898,10 +908,12 @@ def inertia_x( Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.inertia_x(puma.qn) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.inertia_x(puma.qn) .. rubric:: Notes @@ -1016,10 +1028,12 @@ def coriolis_x( Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.coriolis_x(puma.qn, 0.5 * np.ones((6,))) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.coriolis_x(puma.qn, 0.5 * np.ones((6,))) .. rubric:: Notes @@ -1135,10 +1149,12 @@ def gravload_x( Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.gravload_x(puma.qn) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.gravload_x(puma.qn) .. rubric:: Notes @@ -1321,10 +1337,12 @@ def itorque(self: RobotProto, q, qdd): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> puma = rtb.models.DH.Puma560() - >>> puma.itorque(puma.qz, 0.5 * np.ones((6,))) + + >>> import roboticstoolbox as rtb + >>> puma = rtb.models.DH.Puma560() + >>> puma.itorque(puma.qz, 0.5 * np.ones((6,))) .. rubric:: Notes diff --git a/src/roboticstoolbox/robot/ET.py b/src/roboticstoolbox/robot/ET.py index d191b40ec..363c7442e 100644 --- a/src/roboticstoolbox/robot/ET.py +++ b/src/roboticstoolbox/robot/ET.py @@ -266,14 +266,16 @@ def eta(self) -> float | Sym | None: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.eta - >>> e = ET.Rx(90, 'deg') - >>> e.eta - >>> e = ET.ty() - >>> e.eta + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.eta + >>> e = ET.Rx(90, 'deg') + >>> e.eta + >>> e = ET.ty() + >>> e.eta .. rubric:: Notes @@ -312,12 +314,14 @@ def axis(self) -> str: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.axis - >>> e = ET.Rx(90, 'deg') - >>> e.axis + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.axis + >>> e = ET.Rx(90, 'deg') + >>> e.axis """ return self._axis @@ -332,12 +336,14 @@ def isjoint(self) -> bool: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.isjoint - >>> e = ET.tx() - >>> e.isjoint + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.isjoint + >>> e = ET.tx() + >>> e.isjoint """ return self._joint @@ -355,12 +361,14 @@ def isflip(self) -> bool: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx() - >>> e.T(1) - >>> eflip = ET.tx(flip=True) - >>> eflip.T(1) + + >>> from roboticstoolbox import ET + >>> e = ET.tx() + >>> e.T(1) + >>> eflip = ET.tx(flip=True) + >>> eflip.T(1) """ @@ -376,12 +384,14 @@ def isrotation(self) -> bool: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.isrotation - >>> e = ET.rx() - >>> e.isrotation + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.isrotation + >>> e = ET.rx() + >>> e.isrotation """ @@ -397,12 +407,14 @@ def istranslation(self) -> bool: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.istranslation - >>> e = ET.rx() - >>> e.istranslation + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.istranslation + >>> e = ET.rx() + >>> e.istranslation """ @@ -431,13 +443,15 @@ def jindex(self) -> int | None: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx() - >>> print(e) - >>> e = ET.tx(j=3) - >>> print(e) - >>> print(e.jindex) + + >>> from roboticstoolbox import ET + >>> e = ET.tx() + >>> print(e) + >>> e = ET.tx(j=3) + >>> print(e) + >>> print(e.jindex) """ @@ -482,11 +496,13 @@ def inv(self): Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz(2.5) - >>> print(e) - >>> print(e.inv()) + + >>> from roboticstoolbox import ET + >>> e = ET.Rz(2.5) + >>> print(e) + >>> print(e.inv()) """ # noqa @@ -514,12 +530,14 @@ def A(self, q: float | Sym = 0.0) -> ndarray: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tx(1) - >>> e.A() - >>> e = ET.tx() - >>> e.A(0.7) + + >>> from roboticstoolbox import ET + >>> e = ET.tx(1) + >>> e.A() + >>> e = ET.tx() + >>> e.A(0.7) """ try: @@ -930,12 +948,14 @@ def A(self, q: float | Sym = 0.0) -> ndarray: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET2 - >>> e = ET2.tx(1) - >>> e.A() - >>> e = ET2.tx() - >>> e.A(0.7) + + >>> from roboticstoolbox import ET2 + >>> e = ET2.tx(1) + >>> e.A() + >>> e = ET2.tx() + >>> e.A(0.7) """ diff --git a/src/roboticstoolbox/robot/ETS.py b/src/roboticstoolbox/robot/ETS.py index 548029894..8dd4b0a25 100644 --- a/src/roboticstoolbox/robot/ETS.py +++ b/src/roboticstoolbox/robot/ETS.py @@ -134,18 +134,20 @@ def __str__(self, q: str | None = None): Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz() * ET.tx(1) * ET.Rz() - >>> print(e[:2]) - >>> print(e) - >>> print(e.__str__("")) - >>> print(e.__str__("θ{0}")) # numbering from 0 - >>> print(e.__str__("θ{1}")) # numbering from 1 - >>> # explicit joint indices - >>> e = ET.Rz(jindex=3) * ET.tx(1) * ET.Rz(jindex=4) - >>> print(e) - >>> print(e.__str__("θ{0}")) + + >>> from roboticstoolbox import ET + >>> e = ET.Rz() * ET.tx(1) * ET.Rz() + >>> print(e[:2]) + >>> print(e) + >>> print(e.__str__("")) + >>> print(e.__str__("θ{0}")) # numbering from 0 + >>> print(e.__str__("θ{1}")) # numbering from 1 + >>> # explicit joint indices + >>> e = ET.Rz(jindex=3) * ET.tx(1) * ET.Rz(jindex=4) + >>> print(e) + >>> print(e.__str__("θ{0}")) Angular parameters are converted to degrees, except if they are symbolic. @@ -231,6 +233,7 @@ def _repr_pretty_(self, p, cycle): Examples -------- + In [1]: e Out [1]: R(q0) ⊕ tx(1) ⊕ R(q1) ⊕ tx(1) @@ -247,10 +250,12 @@ def joint_idx(self) -> list[int]: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) - >>> e.joint_idx() + + >>> from roboticstoolbox import ET + >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) + >>> e.joint_idx() """ @@ -265,10 +270,12 @@ def joints(self) -> list[ET]: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) - >>> e.joints() + + >>> from roboticstoolbox import ET + >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) + >>> e.joints() """ @@ -283,10 +290,12 @@ def jindex_set(self) -> set[int]: # Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1) - >>> e.jointset() + + >>> from roboticstoolbox import ET + >>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1) + >>> e.jointset() """ @@ -302,10 +311,12 @@ def jindices(self) -> NDArray: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1) - >>> e.jointset() + + >>> from roboticstoolbox import ET + >>> e = ET.Rz(jindex=1) * ET.tx(jindex=2) * ET.Rz(jindex=1) * ET.tx(1) + >>> e.jointset() """ @@ -330,10 +341,12 @@ def qlim(self): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot.qlim + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot.qlim """ @@ -384,10 +397,12 @@ def structure(self) -> str: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.tz() * ET.tx(1) * ET.Rz() * ET.tx(1) - >>> e.structure + + >>> from roboticstoolbox import ET + >>> e = ET.tz() * ET.tx(1) * ET.Rz() * ET.tx(1) + >>> e.structure """ @@ -407,10 +422,12 @@ def n(self) -> int: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rx() * ET.tx(1) * ET.tz() - >>> e.n + + >>> from roboticstoolbox import ET + >>> e = ET.Rx() * ET.tx(1) * ET.tz() + >>> e.n See Also -------- @@ -432,10 +449,12 @@ def m(self) -> int: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rx() * ET.tx(1) * ET.tz() - >>> e.m + + >>> from roboticstoolbox import ET + >>> e = ET.Rx() * ET.tx(1) * ET.tz() + >>> e.m """ @@ -508,11 +527,13 @@ def inv(self: T) -> T: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz(jindex=2) * ET.tx(1) * ET.Rx(jindex=3,flip=True) * ET.tx(1) - >>> print(e) - >>> print(e.inv()) + + >>> from roboticstoolbox import ET + >>> e = ET.Rz(jindex=2) * ET.tx(1) * ET.Rx(jindex=3,flip=True) * ET.tx(1) + >>> print(e) + >>> print(e.inv()) .. rubric:: Notes @@ -547,12 +568,14 @@ def __getitem__(self, i): Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) - >>> e[0] - >>> e[1] - >>> e[1:3] + + >>> from roboticstoolbox import ET + >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) + >>> e[0] + >>> e[1] + >>> e[1:3] """ return self._data[i] # can be [2] or slice, eg. [3:5] @@ -601,12 +624,14 @@ def random_q(self, i: int = 1) -> NDArray: Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.Panda() - >>> ets = robot.ets() - >>> q = ets.random_q() - >>> q + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.Panda() + >>> ets = robot.ets() + >>> q = ets.random_q() + >>> q """ @@ -643,21 +668,23 @@ class ETS(BaseETS): Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ETS, ET - >>> e = ET.Rz(0.3) # a single ET, rotation about z - >>> ets1 = ETS(e) - >>> len(ets1) - >>> ets2 = ET.Rz(0.3) * ET.tx(2) # an ETS - >>> len(ets2) # of length 2 - >>> ets2[1] # an ET sliced from the ETS + + >>> from roboticstoolbox import ETS, ET + >>> e = ET.Rz(0.3) # a single ET, rotation about z + >>> ets1 = ETS(e) + >>> len(ets1) + >>> ets2 = ET.Rz(0.3) * ET.tx(2) # an ETS + >>> len(ets2) # of length 2 + >>> ets2[1] # an ET sliced from the ETS .. rubric:: References - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part I: - Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022). + Kinematics, Velocity, and Applications." arXiv preprint arXiv:2207.01796 (2022). - J. Haviland, and P. Corke. "Manipulator Differential Kinematics Part II: - Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022). + Acceleration and Advanced Applications." arXiv preprint arXiv:2207.01794 (2022). See Also @@ -760,12 +787,14 @@ def compile(self) -> "ETS": Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.ETS.Panda() - >>> ets = robot.ets() - >>> ets - >>> ets.compile() + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.ETS.Panda() + >>> ets = robot.ets() + >>> ets + >>> ets.compile() See Also -------- @@ -812,12 +841,14 @@ def insert( # type: ignore[override] Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import ET - >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) - >>> f = ET.Ry() - >>> e.insert(2, f) - >>> e + + >>> from roboticstoolbox import ET + >>> e = ET.Rz() * ET.tx(1) * ET.Rz() * ET.tx(1) + >>> f = ET.Ry() + >>> e.insert(2, f) + >>> e """ @@ -854,6 +885,7 @@ def fkine( Examples -------- + The following example makes a ``panda`` robot object, gets the ets, and solves for the forward kinematics at the listed configuration. @@ -915,10 +947,12 @@ def eval( Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> panda = rtb.models.Panda().ets() - >>> panda.eval([0, -0.3, 0, -2.2, 0, 2, 0.7854]) + + >>> import roboticstoolbox as rtb + >>> panda = rtb.models.Panda().ets() + >>> panda.eval([0, -0.3, 0, -2.2, 0, 2, 0.7854]) .. rubric:: Notes @@ -956,6 +990,7 @@ def jacob0( Examples -------- + The following example makes a ``Puma560`` robot object, and solves for the base-frame Jacobian at the zero joint angle configuration @@ -1002,6 +1037,7 @@ def jacobe( Examples -------- + The following example makes a ``Puma560`` robot object, and solves for the end-effector frame Jacobian at the zero joint angle configuration @@ -1075,6 +1111,7 @@ def hessian0( Examples -------- + The following example makes a ``Panda`` robot object, and solves for the base frame Hessian at the given joint angle configuration @@ -1143,6 +1180,7 @@ def hessiane( Examples -------- + The following example makes a ``Panda`` robot object, and solves for the end-effector frame Hessian at the given joint angle configuration @@ -1191,6 +1229,7 @@ def jacob0_analytical( Examples -------- + Makes a robot object and computes the analytic Jacobian for the given joint configuration @@ -1391,6 +1430,7 @@ def partial_fkine0(self, q: ArrayLike, n: int) -> NDArray: Examples -------- + The following example makes a ``Panda`` robot object, and solves for the base-effector frame 4th derivative of the forward kinematics at the given joint angle configuration @@ -1648,6 +1688,7 @@ def ik_LM( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_LM` method. @@ -1737,6 +1778,7 @@ def ik_NR( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ik_NR` method. @@ -1840,6 +1882,7 @@ def ik_GN( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_GN` method. @@ -1982,6 +2025,7 @@ def ikine_LM( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_LM` method. @@ -2090,6 +2134,7 @@ def ikine_NR( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_NR` method. @@ -2208,6 +2253,7 @@ def ikine_GN( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_GN` method. @@ -2366,6 +2412,7 @@ def ikine_QP( Examples -------- + The following example gets the ``ets`` of a ``panda`` robot object, makes a goal pose ``Tep``, and then solves for the joint coordinates which result in the pose ``Tep`` using the `ikine_QP` method. diff --git a/src/roboticstoolbox/robot/Link.py b/src/roboticstoolbox/robot/Link.py index 83625e0f6..2736fb586 100644 --- a/src/roboticstoolbox/robot/Link.py +++ b/src/roboticstoolbox/robot/Link.py @@ -273,12 +273,14 @@ def Ts(self) -> NDArray | None: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import Link, ET - >>> link = Link( ET.tz(0.333) * ET.Rx(90, 'deg') * ET.Rz() ) - >>> link.Ts - >>> link = Link( ET.Rz() ) - >>> link.Ts + + >>> from roboticstoolbox import Link, ET + >>> link = Link( ET.tz(0.333) * ET.Rx(90, 'deg') * ET.Rz() ) + >>> link.Ts + >>> link = Link( ET.Rz() ) + >>> link.Ts """ return self._Ts @@ -449,10 +451,12 @@ def v(self) -> BaseET | None: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import Link, ET, ETS - >>> link = Link( ET.tz(0.333) * ET.Rx(90, 'deg') * ET.Rz() ) - >>> print(link.v) + + >>> from roboticstoolbox import Link, ET, ETS + >>> link = Link( ET.tz(0.333) * ET.Rx(90, 'deg') * ET.Rz() ) + >>> print(link.v) """ return self._v @@ -594,10 +598,12 @@ def hasdynamics(self) -> bool: Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> robot[1].hasdynamics + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> robot[1].hasdynamics """ return self._hasdynamics @@ -943,11 +949,13 @@ def isjoint(self) -> bool: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import models - >>> robot = models.URDF.Panda() - >>> robot[1].isjoint # link with joint - >>> robot[8].isjoint # static link + + >>> from roboticstoolbox import models + >>> robot = models.URDF.Panda() + >>> robot[1].isjoint # link with joint + >>> robot[8].isjoint # static link """ @@ -1015,11 +1023,13 @@ def parent(self) -> Self | None: Examples -------- + .. runblock:: pycon - >>> from roboticstoolbox import models - >>> robot = models.URDF.Panda() - >>> robot[0].parent # base link has no parent - >>> robot[1].parent # second link's parent + + >>> from roboticstoolbox import models + >>> robot = models.URDF.Panda() + >>> robot[0].parent # base link has no parent + >>> robot[1].parent # second link's parent """ @@ -1156,11 +1166,13 @@ def dyn(self, indent=0): Examples -------- + .. runblock:: pycon - >>> import roboticstoolbox as rtb - >>> robot = rtb.models.DH.Puma560() - >>> print(robot.links[2]) # kinematic parameters - >>> print(robot.links[2].dyn()) # dynamic parameters + + >>> import roboticstoolbox as rtb + >>> robot = rtb.models.DH.Puma560() + >>> print(robot.links[2]) # kinematic parameters + >>> print(robot.links[2].dyn()) # dynamic parameters :seealso: :func:`~dyntable` """ diff --git a/src/roboticstoolbox/robot/Robot.py b/src/roboticstoolbox/robot/Robot.py index 05dc0ac8c..507c0f3f8 100644 --- a/src/roboticstoolbox/robot/Robot.py +++ b/src/roboticstoolbox/robot/Robot.py @@ -761,17 +761,15 @@ def manipulability( Various measures are supported: - | Measure | Description | - | ``"yoshikawa"`` | Volume of the velocity ellipsoid, *distance* | - | | from singularity [Yoshikawa85]_ | - | ``"invcondition"``| Inverse condition number of Jacobian, isotropy | - | | of the velocity ellipsoid [Klein87]_ | - | ``"minsingular"`` | Minimum singular value of the Jacobian, | - | | *distance* from singularity [Klein87]_ | - | ``"asada"`` | Isotropy of the task-space acceleration | - | | ellipsoid which is a function of the Cartesian | - | | inertia matrix which depends on the inertial | - | | parameters [Asada83]_ | + - ``"yoshikawa"`` -- volume of the velocity ellipsoid, *distance* + from singularity [Yoshikawa85]_ + - ``"invcondition"`` -- inverse condition number of Jacobian, + isotropy of the velocity ellipsoid [Klein87]_ + - ``"minsingular"`` -- minimum singular value of the Jacobian, + *distance* from singularity [Klein87]_ + - ``"asada"`` -- isotropy of the task-space acceleration ellipsoid + which is a function of the Cartesian inertia matrix which depends + on the inertial parameters [Asada83]_ **Trajectory operation**: @@ -804,8 +802,8 @@ def manipulability( Kinematically Redundant Manipulators. Klein CA, Blaho BE. The International Journal of Robotics Research. 1987;6(2):72-83. doi:10.1177/027836498700600206 - - Robotics, Vision & Control, Chap 8, P. Corke, Springer 2011. + - Robotics, Vision & Control, Chap 8, P. Corke, Springer 2011. .. versionchanged:: 1.0.3 Removed 'both' option for axes, added a custom list option. diff --git a/src/roboticstoolbox/robot/RobotKinematics.py b/src/roboticstoolbox/robot/RobotKinematics.py index 760f14a80..504603467 100644 --- a/src/roboticstoolbox/robot/RobotKinematics.py +++ b/src/roboticstoolbox/robot/RobotKinematics.py @@ -695,15 +695,15 @@ def ik_NR( The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by @@ -809,15 +809,15 @@ def ik_GN( The return value ``sol`` is a tuple with elements: - ============ ========== =============================================== + ============== ========== =============================================== Element Type Description - ============ ========== =============================================== + ============== ========== =============================================== ``q`` ndarray(n) joint coordinates in units of radians or metres ``success`` int whether a solution was found ``iterations`` int total number of iterations ``searches`` int total number of searches ``residual`` float final value of cost function - ============ ========== =============================================== + ============== ========== =============================================== If ``success == 0`` the ``q`` values will be valid numbers, but the solution will be in error. The amount of error is indicated by diff --git a/src/roboticstoolbox/tools/trajectory.py b/src/roboticstoolbox/tools/trajectory.py index cc068b00b..c2161c9d9 100644 --- a/src/roboticstoolbox/tools/trajectory.py +++ b/src/roboticstoolbox/tools/trajectory.py @@ -256,7 +256,7 @@ def qplot(self, **kwargs): """ Plot multi-axis trajectory - :param **kwargs: optional arguments passed to ``qplot`` + :param \*\*kwargs: optional arguments passed to ``qplot`` Plots a multi-axis trajectory, held within the object, as position against time. @@ -816,9 +816,9 @@ def ctraj(T0, T1, t=None, s=None): .. note:: - In the second case ``s`` could be generated by a scalar trajectory - generator such as ``quintic`` or ``trapezoidal`` (default). + generator such as ``quintic`` or ``trapezoidal`` (default). - Orientation interpolation is performed using unit-quaternion - interpolation. + interpolation. :References: - Robotics, Vision & Control in Python, 3e, P. Corke, Springer 2023, Chap 3. diff --git a/tech-debt.md b/tech-debt.md index bfa8cde3d..038c98011 100644 --- a/tech-debt.md +++ b/tech-debt.md @@ -784,6 +784,119 @@ any other `sys.version_info`/Python-3.10-specific conditionals elsewhere in the codebase at that point, so 3.10 cleanup happens in one pass rather than piecemeal. +--- + +## Repeated `:returns:`/`:param:` field markers in `robot/*.py` docstrings + +### Background + +While fixing the "Field list ends without a blank line" Sphinx build warnings +(2026-07-05 — a broken `Examples`/`.. runblock::` template pattern across +`BaseRobot.py`, `ETS.py`, `Link.py`, `ET.py`, `Dynamics.py`, likely from the +same refactor work already covered by the "ETS / fknm / frne refactor" entry +above), several docstrings turned up with **repeated field markers** that +don't actually trigger a Sphinx/docutils warning (repeated field names are +silently accepted, not flagged) but are still wrong: + +- `BaseRobot.hasdynamics`/`hascollision`: two consecutive `:returns:` lines + (only one is really shown depending on renderer; the two sentences should + be merged into one field). +- `BaseRobot.ets`: `:param :param start: ...` / `:param :param end: ...` — + a duplicated `:param` marker, plus a stray trailing colon after the + description. +- `BaseRobot.todegrees`: **six** consecutive `:returns:` lines that are + clearly meant to be one multi-line description. +- A `path`-returning method and a gripper/end-effector method with three + consecutive `:returns:` lines each. +- `BaseRobot` (one of the `q`-random methods, ~line 1804): + `:returns: Random joint configuration :rtype: ndarray(n)` — `:rtype:` + crammed onto the same line as `:returns:` instead of being its own field. + +Left alone deliberately (2026-07-05) since fixing the actual build warnings +was the scoped task — this is docstring *content* quality, not a build +break, and merging multi-sentence explanations correctly needs a human +read of intent rather than a mechanical script. + +### Proposed fix + +Sweep `robot/*.py` for `^\s*:returns:.*\n\s*:returns:` (and `:param:`) +regex hits and manually merge each into a single well-formed field. + +--- + +## `napoleon` + `sphinx_autodoc_typehints`: bare NumPy-style section headers conflict + +### Background + +While fixing Sphinx build warnings (2026-07-05), `BaseRobot.dotfile`'s +docstring kept reporting "Explicit markup ends without a blank line" at a +line that had nothing wrong with it by inspection. Root-caused via an +isolated minimal Sphinx build (bisecting the extension list): the +combination of `sphinx.ext.napoleon` + `sphinx_autodoc_typehints` conflicts +when a docstring mixes bare NumPy-style section headers (`Note` underlined +with `----`, recognized and reformatted by Napoleon's heuristics) with +explicit reST fields (`:param:`, `:returns:`) and typehint injection from +`sphinx_autodoc_typehints`. Neither extension alone reproduces it. + +Confirmed napoleon is still genuinely needed, not just historical baggage: +`tools/urdf/utils.py` and `tools/urdf/urdf.py` have real NumPy-style +`Parameters`/`Returns` docstrings (looks vendored/adapted from an external +URDF library) that Napoleon actually converts. Everywhere else in the +codebase (confirmed via grep) writes explicit reST fields directly and +doesn't need Napoleon's conversion — but two `robot/BaseRobot.py` docstrings +had a stray bare `Note` header mixed into otherwise-reST content, which is +what triggered the conflict. Also found `napoleon_custom_sections = +["Synopsis"]` in `conf.py` was dead config — nothing in the codebase uses a +"Synopsis" section — removed. + +### Proposed fix + +Fixed the two known `Note` occurrences (now `.. rubric:: Notes`, matching +the pattern already used elsewhere in the same file). If this warning +resurfaces elsewhere, the fix is the same: replace the bare NumPy-style +header with the equivalent explicit directive (`.. rubric:: Notes`, +`.. warning::`, etc.) rather than relying on Napoleon to recognize it — +don't touch `tools/urdf/*.py`, which needs Napoleon's real NumPy-style +parsing left alone. + +--- + +## Codebase is mid-migration from NumPy-style to reST-style docstrings + +### Background + +The `Note` header bug above is one instance of a broader pattern: this +codebase has clearly moved from NumPy-style docstrings (bare underlined +section headers — `Parameters`/`Returns`/`Notes`/`See Also`, each followed +by a `----` underline) to explicit reST fields (`:param:`, `:returns:`, +`:seealso:`), but the migration is incomplete. Checked 2026-07-05: the +`:seealso:` field is used **202** times across the codebase — clearly the +intended, current convention — but the vestigial bare `See Also` +NumPy-style heading still appears **48** times across 6 files. Each one is +a latent instance of the same Napoleon-heuristic-recognition risk that hit +`BaseRobot.dotfile`/`random_q` (see above) — most haven't triggered a +visible warning yet only because they haven't hit the right combination of +circumstances, not because they're actually safe. + +The same is likely true for other NumPy-style section names (`Notes`, +`Warning`, `Raises`, `Attributes`, `Examples`) wherever they appear as a +bare underlined heading instead of the reST equivalent — this file only +audited `Note`/`See Also` specifically because those are what broke the +build this session. `tools/urdf/utils.py` and `tools/urdf/urdf.py` are the +one confirmed exception: genuine vendored/adapted NumPy-style docstrings +that Napoleon is correctly converting — don't touch those. + +### Proposed fix + +A future pass should grep for each NumPy-recognized bare section header +(`^\s*(Notes?|Warnings?|Parameters|Returns|Raises|Yields|Attributes|Methods|References|See Also|Examples)\s*$` +followed by a matching-length `-+` underline) outside `tools/urdf/`, and +convert each to its reST equivalent (`:seealso:`, `.. rubric:: Notes`, +`.. warning::`, etc.) — same treatment as this session's `Note` fixes, +just systematically rather than one-off as each breaks the build. + +--- + ## `roboticstoolbox.models.list()` shadows the builtin `list` ### Background