44import numpy as np
55from pytransform3d import rotations
66
7+ from dex_retargeting .constants import OPERATOR2MANO , HandType
78from dex_retargeting .optimizer import Optimizer
89from dex_retargeting .optimizer_utils import LPFilter
910
@@ -39,40 +40,37 @@ def __init__(
3940 # Warm started
4041 self .is_warm_started = False
4142
42- # TODO: hack here
43- self .scene = None
44-
45- def warm_start (self , wrist_pos : np .ndarray , wrist_orientation : np .ndarray , global_rot : np .array ):
43+ def warm_start (
44+ self ,
45+ wrist_pos : np .ndarray ,
46+ wrist_quat : np .ndarray ,
47+ hand_type : HandType = HandType .right ,
48+ is_mano_convention : bool = False ,
49+ ):
4650 """
4751 Initialize the wrist joint pose using analytical computation instead of retargeting optimization.
4852 This function is specifically for position retargeting with the flying robot hand, i.e. has 6D free joint
4953 You are not expected to use this function for vector retargeting, e.g. when you are working on teleoperation
54+
5055 Args:
5156 wrist_pos: position of the hand wrist, typically from human hand pose
52- wrist_orientation: orientation of the hand orientation, typically from human hand pose in MANO convention
53- global_rot:
54-
57+ wrist_quat: quaternion of the hand wrist, the same convention as the operator frame definition if not is_mano_convention
58+ hand_type: hand type, used to determine the operator2mano matrix
59+ is_mano_convention: whether the wrist_quat is in mano convention
5560 """
5661 # This function can only be used when the first joints of robot are free joints
57- if len (wrist_pos ) != 3 :
58- raise ValueError (f"Wrist pos:{ wrist_pos } is not a 3-dim vector." )
59- if len (wrist_orientation ) != 3 :
60- raise ValueError (f"Wrist orientation:{ wrist_orientation } is not a 3-dim vector." )
6162
62- if np . linalg . norm ( wrist_orientation ) < 1e- 3 :
63- mat = np . eye ( 3 )
64- else :
65- mat = rotations . matrix_from_compact_axis_angle ( wrist_orientation )
63+ if len ( wrist_pos ) != 3 :
64+ raise ValueError ( f"Wrist pos: { wrist_pos } is not a 3-dim vector." )
65+ if len ( wrist_quat ) != 4 :
66+ raise ValueError ( f"Wrist quat: { wrist_quat } is not a 4-dim vector." )
6667
68+ operator2mano = OPERATOR2MANO [hand_type ] if is_mano_convention else np .eye (3 )
6769 robot = self .optimizer .robot
68- operator2mano = np .array ([[0 , 0 , - 1 ], [- 1 , 0 , 0 ], [0 , 1 , 0 ]])
69- mat = global_rot .T @ mat @ operator2mano
7070 target_wrist_pose = np .eye (4 )
71- target_wrist_pose [:3 , :3 ] = mat
71+ target_wrist_pose [:3 , :3 ] = rotations . matrix_from_quaternion ( wrist_quat ) @ operator2mano . T
7272 target_wrist_pose [:3 , 3 ] = wrist_pos
7373
74- wrist_link_name = self .optimizer .wrist_link_name
75- wrist_link_id = self .optimizer .robot .get_link_index (wrist_link_name )
7674 name_list = [
7775 "dummy_x_translation_joint" ,
7876 "dummy_y_translation_joint" ,
@@ -81,6 +79,9 @@ def warm_start(self, wrist_pos: np.ndarray, wrist_orientation: np.ndarray, globa
8179 "dummy_y_rotation_joint" ,
8280 "dummy_z_rotation_joint" ,
8381 ]
82+ wrist_link_id = robot .get_joint_parent_child_frames (name_list [5 ])[1 ]
83+
84+ # Set the dummy joints angles to zero
8485 old_qpos = robot .q0
8586 new_qpos = old_qpos .copy ()
8687 for num , joint_name in enumerate (self .optimizer .target_joint_names ):
@@ -128,6 +129,13 @@ def set_qpos(self, robot_qpos: np.ndarray):
128129 target_qpos = robot_qpos [self .optimizer .idx_pin2target ]
129130 self .last_qpos = target_qpos
130131
132+ def get_qpos (self , fixed_qpos : np .ndarray | None = None ):
133+ robot_qpos = np .zeros (self .optimizer .robot .dof )
134+ robot_qpos [self .optimizer .idx_pin2target ] = self .last_qpos
135+ if fixed_qpos is not None :
136+ robot_qpos [self .optimizer .idx_pin2fixed ] = fixed_qpos
137+ return robot_qpos
138+
131139 def verbose (self ):
132140 min_value = self .optimizer .opt .last_optimum_value ()
133141 print (f"Retargeting { self .num_retargeting } times takes: { self .accumulated_time } s" )
0 commit comments