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)