Examples
This section demonstrates how to use the DexRobot Kinematics library with complete example scripts.
Hardware control using finger inverse kinematics
In this example, we solve inverse kinematics for a finger, and send the resulting joint angles to DexHand using the pyzlg_dexhand library.
examples/finger_ik_hardware.py
1"""
2Solve IK for a single finger and directly control the hardware.
3
4The code works for the right hand by default, but you can change the hand as needed.
5"""
6
7import numpy as np
8import time
9from dexrobot_kinematics.hand import RightHandKinematics
10from dexrobot_kinematics.utils.types import Position
11from dexrobot_kinematics.utils.hardware import JointMapping
12from pyzlg_dexhand.dexhand_interface import RightDexHand
13
14# Initialize hand
15kin = RightHandKinematics()
16hand = RightDexHand()
17joint_mapping = JointMapping(prefix="r")
18
19# Define a circular trajectory
20center = Position(x=0.01, y=0.04, z=0.22)
21radius = 0.05
22steps = 20
23
24# Simulate motion
25for i in range(2 * steps):
26 # Calculate position along circle
27 if i < steps:
28 angle = np.pi * i / steps
29 else:
30 angle = np.pi * (2 * steps - i) / steps
31 target = Position(
32 x=center.x + radius * np.sin(angle),
33 y=center.y,
34 z=center.z + radius * np.cos(angle),
35 )
36
37 # Solve IK
38 joint_angles, success = kin.inverse_kinematics_finger(
39 finger="index", target_pos=target
40 )
41
42 print(f"Step {i}: Pos ({target.x:.4f}, {target.y:.4f}, {target.z:.4f}), Angles {list(joint_angles.values())}, Success: {success}")
43 # In a real system, you would send these angles to the robot
44 commands = joint_mapping.map_command(joint_angles)
45 hand.move_joints(**commands)
46 hand.clear_errors(clear_all=True)
47 time.sleep(0.1)
Interfacing inverse kinematics with ROS
In this example, we solve inverse kinematics for a finger, and publish the resulting joint angles to a ROS topic. The script can be used in combination with ROS nodes in pyzlg_dexhand or dexrobot_mujoco to control either hardware or simulated hand.
examples/finger_ik_ros.py
1"""
2Solve IK for a single finger and send the result to ROS/ROS2.
3
4Can be used together with the ROS nodes in dexrobot_mujoco or pyzlg_dexhand to control either the hardware or a simulation.
5"""
6
7import numpy as np
8import time
9from ros_compat import ROSNode
10from sensor_msgs.msg import JointState
11from dexrobot_kinematics.hand import RightHandKinematics
12from dexrobot_kinematics.utils.types import Position
13from dexrobot_kinematics.utils.hardware import JointMapping
14
15
16class DexHandIKNode(ROSNode):
17 def __init__(self):
18 super().__init__("dexhand_ik_node")
19 self.kin = RightHandKinematics()
20 self.joint_pub = self.create_publisher(JointState, "joint_commands", 10)
21 self.timer = self.create_timer(0.1, self.timer_callback)
22 self.counter = 0
23
24 def timer_callback(self):
25 # Define a circular trajectory
26 center = Position(x=0.01, y=0.04, z=0.22)
27 radius = 0.05
28 steps = 20
29
30 # Calculate position along circle
31 i = self.counter
32 self.counter += 1
33 if i < steps:
34 angle = np.pi * i / steps
35 else:
36 angle = np.pi * (2 * steps - i) / steps
37 target = Position(
38 x=center.x + radius * np.sin(angle),
39 y=center.y,
40 z=center.z + radius * np.cos(angle),
41 )
42
43 # Solve IK
44 joint_angles, success = self.kin.inverse_kinematics_finger(
45 finger="index", target_pos=target
46 )
47
48 print(f"Step {i}: Pos ({target.x:.4f}, {target.y:.4f}, {target.z:.4f}), Angles {list(joint_angles.values())}, Success: {success}")
49
50 # Publish joint angles
51 msg = JointState()
52 msg.header.stamp = self.get_ros_time().to_msg()
53 msg.name = list(joint_angles.keys())
54 msg.position = list(joint_angles.values())
55 self.joint_pub.publish(msg)
56
57if __name__ == "__main__":
58 node = DexHandIKNode()
59 node.spin()
Forward kinematics based on hardware feedback
In this example, we read joint angles from DexHand using the pyzlg_dexhand library, and compute the forward kinematics to get the fingerpad and fingertip poses.
examples/fk_hardware.py
1"""
2Run FK to obtain fingertip and fingerpad positions, from hardware joint angle readings.
3"""
4
5import numpy as np
6from dexrobot_kinematics.hand import RightHandKinematics
7from dexrobot_kinematics.utils.types import Position, Pose
8from dexrobot_kinematics.utils.hardware import JointMapping
9from pyzlg_dexhand.dexhand_interface import RightDexHand
10
11# Initialize hand
12kin = RightHandKinematics()
13hand = RightDexHand()
14joint_mapping = JointMapping(prefix="r")
15
16# Drive the hand joints to a known position and read feedback
17commands = {
18 "th_rot": 30,
19 "th_mcp": 30,
20 "th_dip": 30,
21 "ff_spr": 20,
22 "ff_mcp": 30,
23 "ff_dip": 30,
24 "mf_mcp": 30,
25 "mf_dip": 30,
26 "rf_mcp": 30,
27 "rf_dip": 30,
28 "lf_mcp": 30,
29 "lf_dip": 30,
30}
31for i in range(10):
32 hand.move_joints(**commands)
33 hand.clear_errors(clear_all=True)
34feedback = hand.get_feedback()
35hardware_feedback_angles = {name: joint.angle for (name, joint) in feedback.joints.items()}
36joint_angles = joint_mapping.map_feedback(hardware_feedback_angles)
37
38# Define base pose of the hand
39R = pin.utils.rpyToMatrix(0, np.pi / 2, 0)
40t = np.array([1.0, 0.0, 0.0])
41base_pose = Pose(position=Position.from_array(t), orientation=R)
42
43# Run forward kinematics
44fingertip_poses_hand = kin.forward_kinematics(joint_angles, frame="hand", end_effector="fingertip")
45fingerpad_poses_hand = kin.forward_kinematics(joint_angles, frame="hand", end_effector="fingerpad")
46fingertip_poses_world = kin.forward_kinematics(joint_angles, base_pose=base_pose, frame="world", end_effector="fingertip")
47fingerpad_poses_world = kin.forward_kinematics(joint_angles, base_pose=base_pose, frame="world", end_effector="fingerpad")
48
49# Print results tables
50print("Fingertip poses (hand frame):")
51print("Finger | Position (m) | Quaternion")
52for finger, pose in fingertip_poses_hand.items():
53 print(f"{finger:6} | {pose.position.to_array()} | {pose.orientation.to_quaternion()}")
54print("\nFingerpad poses (hand frame):")
55print("Finger | Position (m) | Quaternion")
56for finger, pose in fingerpad_poses_hand.items():
57 print(f"{finger:6} | {pose.position.to_array()} | {pose.orientation.to_quaternion()}")
58print("\nFingertip poses (world frame):")
59print("Finger | Position (m) | Quaternion")
60for finger, pose in fingertip_poses_world.items():
61 print(f"{finger:6} | {pose.position.to_array()} | {pose.orientation.to_quaternion()}")
62print("\nFingerpad poses (world frame):")
63print("Finger | Position (m) | Quaternion")
64for finger, pose in fingerpad_poses_world.items():
65 print(f"{finger:6} | {pose.position.to_array()} | {pose.orientation.to_quaternion()}")