7
7
8
8
This module provides integration between Pink inverse kinematics solver and IsaacLab.
9
9
Pink is a differentiable inverse kinematics solver framework that provides task-space control capabilities.
10
+
11
+ Reference:
12
+ Pink IK Solver: https://github.com/stephane-caron/pink
10
13
"""
11
14
15
+ from __future__ import annotations
16
+
12
17
import numpy as np
13
18
import torch
19
+ from typing import TYPE_CHECKING
14
20
15
21
from pink import solve_ik
16
22
from pink .configuration import Configuration
21
27
from isaaclab .utils .string import resolve_matching_names_values
22
28
23
29
from .null_space_posture_task import NullSpacePostureTask
24
- from .pink_ik_cfg import PinkIKControllerCfg
30
+
31
+ if TYPE_CHECKING :
32
+ from .pink_ik_cfg import PinkIKControllerCfg
25
33
26
34
27
35
class PinkIKController :
28
36
"""Integration of Pink IK controller with Isaac Lab.
29
37
30
- The Pink IK controller is available at: https://github.com/stephane-caron/pink
38
+ The Pink IK controller solves differential inverse kinematics through weighted tasks. Each task is defined
39
+ by a residual function e(q) that is driven to zero (e.g., e(q) = p_target - p_ee(q) for end-effector positioning).
40
+ The controller computes joint velocities v satisfying J_e(q)v = -αe(q), where J_e(q) is the task Jacobian.
41
+ Multiple tasks are resolved through weighted optimization, formulating a quadratic program that minimizes
42
+ weighted task errors while respecting joint velocity limits.
43
+
44
+ It supports user defined tasks, and we have provided a NullSpacePostureTask for maintaining desired joint configurations.
45
+
46
+ Reference:
47
+ Pink IK Solver: https://github.com/stephane-caron/pink
31
48
"""
32
49
33
50
def __init__ (self , cfg : PinkIKControllerCfg , robot_cfg : ArticulationCfg , device : str ):
34
51
"""Initialize the Pink IK Controller.
35
52
36
53
Args:
37
- cfg: The configuration for the controller.
38
- device: The device to use for computations (e.g., 'cuda:0').
54
+ cfg: The configuration for the Pink IK controller containing task definitions, solver parameters,
55
+ and joint configurations.
56
+ robot_cfg: The robot articulation configuration containing initial joint positions and robot
57
+ specifications.
58
+ device: The device to use for computations (e.g., 'cuda:0', 'cpu').
59
+
60
+ Raises:
61
+ KeyError: When Pink joint names cannot be matched to robot configuration joint positions.
39
62
"""
40
63
# Initialize the robot model from URDF and mesh files
41
64
self .robot_wrapper = RobotWrapper .BuildFromURDF (cfg .urdf_path , cfg .mesh_path , root_joint = None )
@@ -63,6 +86,7 @@ def __init__(self, cfg: PinkIKControllerCfg, robot_cfg: ArticulationCfg, device:
63
86
64
87
# Set the default targets for each task from the configuration
65
88
for task in cfg .variable_input_tasks :
89
+ # If task is a NullSpacePostureTask, set the target to the initial joint positions
66
90
if isinstance (task , NullSpacePostureTask ):
67
91
task .set_target (self .init_joint_positions )
68
92
continue
@@ -91,30 +115,29 @@ def __init__(self, cfg: PinkIKControllerCfg, robot_cfg: ArticulationCfg, device:
91
115
self .cfg = cfg
92
116
self .device = device
93
117
94
- def reorder_array (self , input_array : list [float ], reordering_array : list [int ]) -> list [float ]:
118
+ def _reorder_array (self , input_array : list [float ], reordering_array : list [int ]) -> list [float ]:
95
119
"""Reorder the input array based on the provided ordering.
96
120
121
+ This utility method is used to convert between Isaac Lab and Pink joint ordering conventions.
122
+
97
123
Args:
98
- input_array: The array to reorder.
99
- reordering_array: The indices to use for reordering.
124
+ input_array: The array to reorder, typically joint positions or velocities .
125
+ reordering_array: The indices to use for reordering, mapping from source to target ordering .
100
126
101
127
Returns:
102
- Reordered array.
128
+ Reordered array following the target joint ordering convention .
103
129
"""
104
130
return [input_array [i ] for i in reordering_array ]
105
131
106
- def initialize (self ):
107
- """Initialize the internals of the controller.
108
-
109
- This method is called during setup but before the first compute call.
110
- """
111
- pass
112
-
113
132
def update_null_space_joint_targets (self , curr_joint_pos : np .ndarray ):
114
133
"""Update the null space joint targets.
115
134
135
+ This method updates the target joint positions for null space posture tasks based on the current
136
+ joint configuration. This is useful for maintaining desired joint configurations when the primary
137
+ task allows redundancy.
138
+
116
139
Args:
117
- curr_joint_pos: The current joint positions.
140
+ curr_joint_pos: The current joint positions of shape (num_joints,) .
118
141
"""
119
142
for task in self .cfg .variable_input_tasks :
120
143
if isinstance (task , NullSpacePostureTask ):
@@ -127,15 +150,20 @@ def compute(
127
150
) -> torch .Tensor :
128
151
"""Compute the target joint positions based on current state and tasks.
129
152
153
+ Performs inverse kinematics using the Pink solver to compute target joint positions that satisfy
154
+ the defined tasks. The solver uses quadratic programming to find optimal joint velocities that
155
+ minimize task errors while respecting constraints.
156
+
130
157
Args:
131
- curr_joint_pos: The current joint positions.
132
- dt: The time step for computing joint position changes.
158
+ curr_joint_pos: The current joint positions of shape (num_joints,) .
159
+ dt: The time step for computing joint position changes in seconds .
133
160
134
161
Returns:
135
- The target joint positions as a tensor.
162
+ The target joint positions as a tensor of shape (num_joints,) on the specified device.
163
+ If the IK solver fails, returns the current joint positions unchanged to maintain stability.
136
164
"""
137
165
# Initialize joint positions for Pink, including the root and universal joints
138
- joint_positions_pink = np .array (self .reorder_array (curr_joint_pos , self .isaac_lab_to_pink_ordering ))
166
+ joint_positions_pink = np .array (self ._reorder_array (curr_joint_pos , self .isaac_lab_to_pink_ordering ))
139
167
140
168
# Update Pink's robot configuration with the current joint positions
141
169
self .pink_configuration .update (joint_positions_pink )
@@ -165,7 +193,7 @@ def compute(
165
193
166
194
# Reorder the joint angle changes back to Isaac Lab conventions
167
195
joint_vel_isaac_lab = torch .tensor (
168
- self .reorder_array (pink_joint_angle_changes , self .pink_to_isaac_lab_ordering ),
196
+ self ._reorder_array (pink_joint_angle_changes , self .pink_to_isaac_lab_ordering ),
169
197
device = self .device ,
170
198
dtype = torch .float ,
171
199
)
0 commit comments