@@ -1878,180 +1878,9 @@ def cross(a, b):
1878
1878
1879
1879
return H
1880
1880
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
- """
2046
1881
2047
- # link = self.base_link
2048
1882
2049
- def recurse (link , indent = 0 ):
2050
- print (' ' * indent * 2 , link .name )
2051
- for child in link .child :
2052
- recurse (child , indent + 1 )
2053
1883
2054
- recurse (self .base_link )
2055
1884
2056
1885
def jacobev (
2057
1886
self , q , end = None , start = None ,
0 commit comments