Example: TriFingerPro Forward/Inverse KinematicsΒΆ
Demo computing forward and inverse kinematics for the TriFingerPro robot.
#!/usr/bin/env python3
"""Demo computing forward and inverse kinematics for the TriFingerPro robot.
Uses forward and inverse kinematics to move the finger tips synchronously back
and forth on the y-axis.
For the computation the `Kinematics` class from the robot_properties_fingers package is
used. The path to the robots URDF model is acquired using a helper function from the
trifinger_simulation package. So these packages need to be installed.
For complete documentation of the `Kinematics` class see
https://open-dynamic-robot-initiative.github.io/robot_properties_fingers/robot_properties_fingers.html#robot_properties_fingers.Kinematics
"""
import argparse
import copy
import os
import numpy as np
from ament_index_python.packages import get_package_share_directory
import robot_fingers
import robot_interfaces
import robot_properties_fingers
import trifinger_simulation.finger_types_data
def init_kinematics():
"""Initialise the kinematics calculator for TriFingerPro."""
robot_properties_path = get_package_share_directory("robot_properties_fingers")
urdf_file = trifinger_simulation.finger_types_data.get_finger_urdf("trifingerpro")
finger_urdf_path = os.path.join(robot_properties_path, "urdf", urdf_file)
kinematics = robot_properties_fingers.Kinematics(
finger_urdf_path,
["finger_tip_link_0", "finger_tip_link_120", "finger_tip_link_240"],
)
return kinematics
def main():
argparser = argparse.ArgumentParser(description=__doc__)
argparser.add_argument(
"--single-process",
action="store_true",
help="Run back- and front-end in the same process.",
)
args = argparser.parse_args()
if args.single_process:
robot = robot_fingers.Robot.create_by_name("trifingerpro")
robot.initialize()
frontend = robot.frontend
else:
robot_data = robot_interfaces.trifinger.MultiProcessData("trifinger", False)
frontend = robot_interfaces.trifinger.Frontend(robot_data)
kinematics = init_kinematics()
# initial angular joint positions in radian
angular_joint_positions = np.array([0, 0.9, -1.7] * 3)
# Use forward kinematics to get the initial finger tip positions.
# The returned value is a list of (x, y, z)-positions of the three finger
initial_cartesian_tip_positions = kinematics.forward_kinematics(
angular_joint_positions
)
for i, pos in enumerate(initial_cartesian_tip_positions):
print("Initial position of finger tip {}: {}".format(i, pos))
# move the tips back and forth on the y-axis
cartesian_tip_positions = copy.deepcopy(initial_cartesian_tip_positions)
distance = 0.05
n_steps = 1000
t = 0
while True:
# apply action and get observation
finger_action = robot_interfaces.trifinger.Action(
position=angular_joint_positions
)
t = frontend.append_desired_action(finger_action)
observation = frontend.get_observation(t)
# update desired tip positions
for i in range(len(initial_cartesian_tip_positions)):
dy = distance * np.sin(t * np.pi / n_steps)
cartesian_tip_positions[i][1] = initial_cartesian_tip_positions[i][1] + dy
# use inverse kinematics to get the corresponding joint angles
angular_joint_positions, err = kinematics.inverse_kinematics(
cartesian_tip_positions, observation.position
)
print("IK error:", [round(np.linalg.norm(e), 4) for e in err])
if __name__ == "__main__":
main()
This example is also shipped with the package and can be found in
demos/demo_trifingerpro_kinematics.py.