Skip to content

Commit ea3dbc5

Browse files
committed
attempt to move jacobm upto Robot
1 parent 79c2271 commit ea3dbc5

File tree

2 files changed

+98
-176
lines changed

2 files changed

+98
-176
lines changed

roboticstoolbox/robot/ERobot.py

Lines changed: 0 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,180 +1878,9 @@ def cross(a, b):
18781878

18791879
return H
18801880

1881-
def jacobm(self, q=None, J=None, H=None, end=None, start=None, axes='all'):
1882-
r"""
1883-
Calculates the manipulability Jacobian. This measure relates the rate
1884-
of change of the manipulability to the joint velocities of the robot.
1885-
One of J or q is required. Supply J and H if already calculated to
1886-
save computation time
1887-
1888-
:param q: The joint angles/configuration of the robot (Optional,
1889-
if not supplied will use the stored q values).
1890-
:type q: float ndarray(n)
1891-
:param J: The manipulator Jacobian in any frame
1892-
:type J: float ndarray(6,n)
1893-
:param H: The manipulator Hessian in any frame
1894-
:type H: float ndarray(6,n,n)
1895-
:param end: the final link or Gripper which the Hessian represents
1896-
:type end: str or ELink or Gripper
1897-
:param start: the first link which the Hessian represents
1898-
:type start: str or ELink
1899-
1900-
:return: The manipulability Jacobian
1901-
:rtype: float ndarray(n)
1902-
1903-
Yoshikawa's manipulability measure
1904-
1905-
.. math::
1906-
1907-
m(\vec{q}) = \sqrt{\mat{J}(\vec{q}) \mat{J}(\vec{q})^T}
1908-
1909-
This method returns its Jacobian with respect to configuration
1910-
1911-
.. math::
1912-
1913-
\frac{\partial m(\vec{q})}{\partial \vec{q}}
1914-
1915-
:references:
1916-
- Kinematic Derivatives using the Elementary Transform
1917-
Sequence, J. Haviland and P. Corke
1918-
"""
1919-
1920-
end, start, _ = self._get_limit_links(end, start)
1921-
path, n, _ = self.get_path(end, start)
1922-
1923-
if axes == 'all':
1924-
axes = [True, True, True, True, True, True]
1925-
elif axes.startswith('trans'):
1926-
axes = [True, True, True, False, False, False]
1927-
elif axes.startswith('rot'):
1928-
axes = [False, False, False, True, True, True]
1929-
else:
1930-
raise ValueError('axes must be all, trans or rot')
1931-
1932-
if J is None:
1933-
if q is None:
1934-
q = np.copy(self.q)
1935-
else:
1936-
q = getvector(q, self.n)
1937-
1938-
J = self.jacob0(q, start=start, end=end)
1939-
else:
1940-
verifymatrix(J, (6, n))
1941-
1942-
if H is None:
1943-
H = self.hessian0(J0=J, start=start, end=end)
1944-
else:
1945-
verifymatrix(H, (6, n, n))
1946-
1947-
manipulability = self.manipulability(
1948-
q, J=J, start=start, end=end, axes=axes)
1949-
1950-
J = J[axes, :]
1951-
H = H[axes, :, :]
1952-
1953-
b = np.linalg.inv(J @ np.transpose(J))
1954-
Jm = np.zeros((n, 1))
1955-
1956-
for i in range(n):
1957-
c = J @ np.transpose(H[:, :, i])
1958-
Jm[i, 0] = manipulability * \
1959-
np.transpose(c.flatten('F')) @ b.flatten('F')
1960-
1961-
return Jm
1962-
1963-
def __str__(self):
1964-
"""
1965-
Pretty prints the ETS Model of the robot.
1966-
1967-
:return: Pretty print of the robot model
1968-
:rtype: str
1969-
1970-
.. note::
1971-
- Constant links are shown in blue.
1972-
- End-effector links are prefixed with an @
1973-
- Angles in degrees
1974-
- The robot base frame is denoted as ``BASE`` and is equal to the
1975-
robot's ``base`` attribute.
1976-
"""
1977-
table = ANSITable(
1978-
Column("id", headalign="^", colalign=">"),
1979-
Column("link", headalign="^", colalign="<"),
1980-
Column("joint", headalign="^", colalign=">"),
1981-
Column("parent", headalign="^", colalign="<"),
1982-
Column("ETS", headalign="^", colalign="<"),
1983-
border="thin")
1984-
for k, link in enumerate(self):
1985-
color = "" if link.isjoint else "<<blue>>"
1986-
ee = "@" if link in self.ee_links else ""
1987-
ets = link.ets()
1988-
if link.parent is None:
1989-
parent_name = "BASE"
1990-
else:
1991-
parent_name = link.parent.name
1992-
s = ets.__str__(f"q{link._jindex}")
1993-
if len(s) > 0:
1994-
s = " \u2295 " + s
1995-
1996-
if link.isjoint:
1997-
if link._joint_name is not None:
1998-
jname = link._joint_name
1999-
else:
2000-
jname = link.jindex
2001-
else:
2002-
jname = ''
2003-
table.row(
2004-
k,
2005-
color + ee + link.name,
2006-
jname,
2007-
parent_name,
2008-
f"{{{link.name}}} = {{{parent_name}}}{s}"
2009-
)
2010-
2011-
s = self.name
2012-
if self.manufacturer is None or len(self.manufacturer) == 0:
2013-
s += f" (by {self.manufacturer})"
2014-
s += f", {self.n} axes ({self.structure})"
2015-
if self.nbranches > 1:
2016-
s += f", {self.nbranches} branches"
2017-
if self._hasdynamics:
2018-
s += ", dynamics"
2019-
if any([len(link.geometry) > 0 for link in self.links]):
2020-
s += ", geometry"
2021-
if any([len(link.collision) > 0 for link in self.links]):
2022-
s += ", collision"
2023-
s += f", ETS model\n"
2024-
2025-
s += str(table)
2026-
s += self.configurations_str()
2027-
2028-
return s
2029-
2030-
def hierarchy(self):
2031-
"""
2032-
Pretty print the robot link hierachy
2033-
2034-
:return: Pretty print of the robot model
2035-
:rtype: str
2036-
2037-
Example:
2038-
2039-
.. runblock:: pycon
2040-
2041-
>>> import roboticstoolbox as rtb
2042-
>>> robot = rtb.models.URDF.Panda()
2043-
>>> robot.hierarchy()
2044-
2045-
"""
20461881

2047-
# link = self.base_link
20481882

2049-
def recurse(link, indent=0):
2050-
print(' ' * indent * 2, link.name)
2051-
for child in link.child:
2052-
recurse(child, indent + 1)
20531883

2054-
recurse(self.base_link)
20551884

20561885
def jacobev(
20571886
self, q, end=None, start=None,

roboticstoolbox/robot/Robot.py

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import copy
33
import numpy as np
44
import roboticstoolbox as rtb
5-
from spatialmath import SE3
5+
from spatialmath import SE3, SE2
66
from spatialmath.base.argcheck import isvector, getvector, getmatrix, \
77
getunit
88
from roboticstoolbox.robot.Link import Link
@@ -632,6 +632,88 @@ def jacob_dot(self, q=None, qd=None, J0=None):
632632
Jd += H[:, :, i] * qd[i]
633633

634634
return Jd
635+
636+
def jacobm(self, q=None, J=None, H=None, end=None, start=None, axes='all'):
637+
r"""
638+
Calculates the manipulability Jacobian. This measure relates the rate
639+
of change of the manipulability to the joint velocities of the robot.
640+
One of J or q is required. Supply J and H if already calculated to
641+
save computation time
642+
643+
:param q: The joint angles/configuration of the robot (Optional,
644+
if not supplied will use the stored q values).
645+
:type q: float ndarray(n)
646+
:param J: The manipulator Jacobian in any frame
647+
:type J: float ndarray(6,n)
648+
:param H: The manipulator Hessian in any frame
649+
:type H: float ndarray(6,n,n)
650+
:param end: the final link or Gripper which the Hessian represents
651+
:type end: str or ELink or Gripper
652+
:param start: the first link which the Hessian represents
653+
:type start: str or ELink
654+
655+
:return: The manipulability Jacobian
656+
:rtype: float ndarray(n)
657+
658+
Yoshikawa's manipulability measure
659+
660+
.. math::
661+
662+
m(\vec{q}) = \sqrt{\mat{J}(\vec{q}) \mat{J}(\vec{q})^T}
663+
664+
This method returns its Jacobian with respect to configuration
665+
666+
.. math::
667+
668+
\frac{\partial m(\vec{q})}{\partial \vec{q}}
669+
670+
:references:
671+
- Kinematic Derivatives using the Elementary Transform
672+
Sequence, J. Haviland and P. Corke
673+
"""
674+
675+
end, start, _ = self._get_limit_links(end, start)
676+
# path, n, _ = self.get_path(end, start)
677+
678+
if axes == 'all':
679+
axes = [True, True, True, True, True, True]
680+
elif axes.startswith('trans'):
681+
axes = [True, True, True, False, False, False]
682+
elif axes.startswith('rot'):
683+
axes = [False, False, False, True, True, True]
684+
else:
685+
raise ValueError('axes must be all, trans or rot')
686+
687+
if J is None:
688+
if q is None:
689+
q = np.copy(self.q)
690+
else:
691+
q = getvector(q, self.n)
692+
693+
J = self.jacob0(q, start=start, end=end)
694+
else:
695+
verifymatrix(J, (6, n))
696+
697+
if H is None:
698+
H = self.hessian0(J0=J, start=start, end=end)
699+
else:
700+
verifymatrix(H, (6, n, n))
701+
702+
manipulability = self.manipulability(
703+
q, J=J, start=start, end=end, axes=axes)
704+
705+
J = J[axes, :]
706+
H = H[axes, :, :]
707+
708+
b = np.linalg.inv(J @ np.transpose(J))
709+
Jm = np.zeros((n, 1))
710+
711+
for i in range(n):
712+
c = J @ np.transpose(H[:, :, i])
713+
Jm[i, 0] = manipulability * \
714+
np.transpose(c.flatten('F')) @ b.flatten('F')
715+
716+
return Jm
635717
# --------------------------------------------------------------------- #
636718

637719
@property
@@ -719,12 +801,23 @@ def base(self):
719801
def base(self, T):
720802
# if not isinstance(T, SE3):
721803
# T = SE3(T)
722-
if T is None or isinstance(T, SE3):
804+
if T is None:
723805
self._base = T
724-
elif SE3.isvalid(T):
725-
self._tool = SE3(T, check=False)
806+
elif isinstance(self, rtb.ERobot2):
807+
# 2D robot
808+
if isinstance(T, SE2):
809+
self._base = T
810+
elif SE2.isvalid(T):
811+
self._tool = SE2(T, check=True)
812+
elif isinstance(self, rtb.Robot):
813+
# all other 3D robots
814+
if isinstance(T, SE3):
815+
self._base = T
816+
elif SE3.isvalid(T):
817+
self._tool = SE3(T, check=True)
818+
726819
else:
727-
raise ValueError('base must be set to None (no tool) or an SE3')
820+
raise ValueError('base must be set to None (no tool), SE2, or SE3')
728821
# --------------------------------------------------------------------- #
729822

730823
@property

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy