2
2
import numpy as np
3
3
import pybullet as pyb
4
4
5
- from .named_tuples import getJointInfo
5
+ from .named_tuples import getJointInfo , getJointStates , getLinkState
6
+ from .math import quaternion_to_matrix
6
7
7
8
8
9
class Robot :
@@ -43,9 +44,9 @@ def get_joint_states(self):
43
44
A tuple ``(q, v)`` where ``q`` is the robot's joint configuration
44
45
and ``v`` is the joint velocity.
45
46
"""
46
- states = pyb . getJointStates (self .uid , self ._joint_indices )
47
- q = np .array ([state [ 0 ] for state in states ])
48
- v = np .array ([state [ 1 ] for state in states ])
47
+ states = getJointStates (self .uid , self ._joint_indices )
48
+ q = np .array ([state . jointPosition for state in states ])
49
+ v = np .array ([state . jointVelocity for state in states ])
49
50
return q , v
50
51
51
52
def reset_joint_configuration (self , q ):
@@ -79,11 +80,11 @@ def command_velocity(self, u):
79
80
targetVelocities = list (u ),
80
81
)
81
82
82
- def get_link_pose (self , link_idx = None ):
83
- """Get the pose of a link.
83
+ def get_link_com_pose (self , link_idx = None ):
84
+ """Get the pose of a link's center of mass .
84
85
85
- The pose is computed about the link's CoM with respect to the world
86
- frame.
86
+ The pose is computed about the link's center of mass with respect to
87
+ the world frame.
87
88
88
89
Parameters
89
90
----------
@@ -100,15 +101,42 @@ def get_link_pose(self, link_idx=None):
100
101
"""
101
102
if link_idx is None :
102
103
link_idx = self .tool_idx
103
- state = pyb .getLinkState (self .uid , link_idx , computeForwardKinematics = True )
104
- pos , orn = state [4 ], state [5 ]
105
- return np .array (pos ), np .array (orn )
104
+ state = getLinkState (self .uid , link_idx , computeForwardKinematics = True )
105
+ return np .array (state .linkWorldPosition ), np .array (
106
+ state .linkWorldOrientation
107
+ )
106
108
107
- def get_link_velocity (self , link_idx = None ):
108
- """Get the velocity of a link.
109
+ def get_link_frame_pose (self , link_idx = None ):
110
+ """Get the pose of a link's URDF frame .
109
111
110
- The velocity is computed about the link's CoM with respect to the world
111
- frame.
112
+ The pose is computed about the link's parent joint position, which is
113
+ its URDF frame.
114
+
115
+ Parameters
116
+ ----------
117
+ link_idx :
118
+ Index of the link to use. If not provided, defaults to the end
119
+ effector ``self.tool_idx``.
120
+
121
+ Returns
122
+ -------
123
+ :
124
+ A tuple containing the position and orientation quaternion of the
125
+ link's frame with respect to the world. The quaternion is
126
+ represented in xyzw order.
127
+ """
128
+ if link_idx is None :
129
+ link_idx = self .tool_idx
130
+ state = getLinkState (self .uid , link_idx , computeForwardKinematics = True )
131
+ return np .array (state .worldLinkFramePosition ), np .array (
132
+ state .worldLinkFrameOrientation
133
+ )
134
+
135
+ def get_link_com_velocity (self , link_idx = None ):
136
+ """Get the velocity of a link's center of mass.
137
+
138
+ The velocity is computed about the link's center of mass with respect
139
+ to the world frame.
112
140
113
141
Parameters
114
142
----------
@@ -124,25 +152,36 @@ def get_link_velocity(self, link_idx=None):
124
152
"""
125
153
if link_idx is None :
126
154
link_idx = self .tool_idx
127
- state = pyb .getLinkState (
155
+ state = getLinkState (
156
+ self .uid ,
157
+ link_idx ,
158
+ computeLinkVelocity = True ,
159
+ )
160
+ v_com = np .array (state .worldLinkLinearVelocity )
161
+ ω_com = np .array (state .worldLinkAngularVelocity )
162
+ return v_com , ω_com
163
+
164
+ def get_link_frame_velocity (self , link_idx = None ):
165
+ if link_idx is None :
166
+ link_idx = self .tool_idx
167
+ state = getLinkState (
128
168
self .uid ,
129
169
link_idx ,
130
170
computeLinkVelocity = True ,
171
+ computeForwardKinematics = True ,
131
172
)
132
- return np .array (state [- 2 ]), np .array (state [- 1 ])
173
+ C = quaternion_to_matrix (state .worldLinkFrameOrientation )
174
+ v_com = np .array (state .worldLinkLinearVelocity )
175
+ ω_com = np .array (state .worldLinkAngularVelocity )
176
+ v = v_com - np .cross (ω_com , C @ state .localInertialFramePosition )
177
+ ω = ω_com
178
+ return v , ω
133
179
134
- def jacobian (self , q = None , link_idx = None , offset = None ):
180
+ def compute_link_jacobian (self , q = None , link_idx = None , offset = None ):
135
181
"""Get the Jacobian of a point on a link at the given configuration.
136
182
137
- Warning
138
- -------
139
- The Jacobian is computed around the link's parent joint position,
140
- whereas ``get_link_pose`` and ``get_link_velocity`` compute the pose
141
- and velocity around the link's center of mass (CoM). To compute the
142
- Jacobian around the CoM, pass in the ``offset`` of the CoM from the
143
- joint position in the local frame. Alternatively, it may be convenient
144
- to simply design your URDF so that the CoM of the link of interest
145
- coincides with the joint origin.
183
+ When ``offset`` is ``None`` or zeros, the Jacobian is computed around
184
+ the URDF link frame (i.e., the parent joint position).
146
185
147
186
See also
148
187
https://github.com/bulletphysics/bullet3/issues/2429#issuecomment-538431246.
@@ -180,3 +219,51 @@ def jacobian(self, q=None, link_idx=None, offset=None):
180
219
Jv , Jw = pyb .calculateJacobian (self .uid , link_idx , offset , q , z , z )
181
220
J = np .vstack ((Jv , Jw ))
182
221
return J
222
+
223
+ def compute_link_frame_jacobian (self , q = None , link_idx = None ):
224
+ """Compute the Jacobian around the URDF link frame.
225
+
226
+ This is the same as calling ``compute_link_jacobian`` with
227
+ ``offset=None``.
228
+
229
+ Parameters
230
+ ----------
231
+ q :
232
+ The joint configuration at which to compute the Jacobian. If no
233
+ configuration is given, then the current one is used.
234
+ link_idx :
235
+ The index of the link to compute the Jacobian for. The end effector
236
+ link ``self.tool_idx`` is used if not given.
237
+
238
+ Returns
239
+ -------
240
+ :
241
+ The :math:`6\\ times n` Jacobian matrix, where :math:`n` is the
242
+ number of joints.
243
+ """
244
+ return self .compute_link_jacobian (q = q , link_idx = link_idx , offset = None )
245
+
246
+ def compute_link_com_jacobian (self , q = None , link_idx = None ):
247
+ """Compute the Jacobian around the link's center of mass.
248
+
249
+ Parameters
250
+ ----------
251
+ q :
252
+ The joint configuration at which to compute the Jacobian. If no
253
+ configuration is given, then the current one is used.
254
+ link_idx :
255
+ The index of the link to compute the Jacobian for. The end effector
256
+ link ``self.tool_idx`` is used if not given.
257
+
258
+ Returns
259
+ -------
260
+ :
261
+ The :math:`6\\ times n` Jacobian matrix, where :math:`n` is the
262
+ number of joints.
263
+ """
264
+ if link_idx is None :
265
+ link_idx = self .tool_idx
266
+ state = getLinkState (self .uid , link_idx )
267
+ return self .compute_link_jacobian (
268
+ q = q , link_idx = link_idx , offset = state .localInertialFramePosition
269
+ )
0 commit comments