Source code for rofunc.utils.robolab.kinematics.ik

from typing import Union, List, Tuple
import torch

from rofunc.utils.robolab.coord import convert_ori_format, convert_quat_order
from rofunc.utils.robolab.kinematics.pytorch_kinematics_utils import build_chain_from_model


[docs]def get_ik_from_chain(chain, goal_pose: Union[torch.Tensor, None, List, Tuple], device, goal_in_rob_tf: bool = True, robot_pose: Union[torch.Tensor, None, List, Tuple] = None, cur_configs=None, num_retries: int = 10): """ Get the inverse kinematics from a serial chain :param chain: only the serial chain is supported :param goal_pose: the pose of the export ee link :param device: the device to run the computation :param goal_in_rob_tf: whether the goal pose is in the robot base frame :param robot_pose: the pose of the robot base frame :param cur_configs: let the ik solver retry from these configurations :param num_retries: the number of retries :return: """ import pytorch_kinematics as pk goal_pos = goal_pose[:3] goal_rot = goal_pose[3:] goal_tf = pk.Transform3d(pos=goal_pos, rot=goal_rot, device=device) if not goal_in_rob_tf: assert robot_pose is not None, "The robot pose must be provided if the goal pose is not in the robot base frame" robot_pos = robot_pose[:3] robot_rot = robot_pose[3:] rob_tf = pk.Transform3d(pos=robot_pos, rot=robot_rot, device=device) goal_tf = rob_tf.inverse().compose(goal_tf) # get robot joint limits lim = torch.tensor(chain.get_joint_limits(), device=device) if cur_configs is not None: cur_configs = torch.tensor(cur_configs, device=device) # create the IK object # see the constructor for more options and their explanations, such as convergence tolerances ik = pk.PseudoInverseIK(chain, max_iterations=30, retry_configs=cur_configs, num_retries=num_retries, joint_limits=lim.T, early_stopping_any_converged=True, early_stopping_no_improvement="all", debug=False, lr=0.2) # solve IK sol = ik.solve(goal_tf) return sol
[docs]def get_ik_from_model(model_path: str, pose: torch.Tensor, device, export_link, verbose=False): """ Get the inverse kinematics from a URDF or MuJoCo XML file :param model_path: the path of the URDF or MuJoCo XML file :param pose: the pose of the end effector, 7D vector with the first 3 elements as position and the last 4 elements as rotation :param device: the device to run the computation :param export_link: the name of the end effector link :param verbose: whether to print the chain :return: the position, rotation of the end effector, and the transformation matrices of all links """ import pytorch_kinematics as pk chain = build_chain_from_model(model_path, verbose) chain = pk.SerialChain(chain, export_link) pos = pose[:3] rot = convert_ori_format(pose[3:], "quat", "euler") sol = get_ik_from_chain(chain, pos, rot, device) return sol
if __name__ == '__main__': model_path = "./simulator/assets/urdf/franka_description/robots/franka_panda.urdf" # device = torch.device("cuda" if torch.cuda.is_available() else "cpu") device = torch.device("cpu") pose = torch.tensor([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0], device=device) sol = get_ik_from_model(model_path, pose, device, export_link="panda_hand") print(sol.solutions) print("Done") import pybullet as p import pybullet_data import pytorch_kinematics as pk search_path = pybullet_data.getDataPath() # visualize everything p.connect(p.GUI) p.setRealTimeSimulation(False) p.configureDebugVisualizer(p.COV_ENABLE_GUI, 0) p.setAdditionalSearchPath(search_path) pos = torch.tensor([0.0, 0.0, 0.0], device=device) rot = torch.tensor([0.0, 0.0, 0.0], device=device) rob_tf = pk.Transform3d(pos=pos, rot=rot, device=device) p.loadURDF("plane.urdf", [0, 0, 0], useFixedBase=True) m = rob_tf.get_matrix() pos = m[0, :3, 3] rot = m[0, :3, :3] quat = pk.matrix_to_quaternion(rot) pos = pos.cpu().numpy() rot = convert_quat_order(quat, "wxyz", "xyzw").cpu().numpy() armId = p.loadURDF(model_path, basePosition=pos, baseOrientation=rot, useFixedBase=True) visId = p.createVisualShape(p.GEOM_MESH, fileName="meshes/cone.obj", meshScale=1.0, rgbaColor=[0., 1., 0., 0.5]) # r = goal_rot[goal_num] # xyzw = pk.wxyz_to_xyzw(pk.matrix_to_quaternion(pk.euler_angles_to_matrix(r, "XYZ"))) # goalId = p.createMultiBody(baseMass=0, baseVisualShapeIndex=visId, # basePosition=goal_pos[goal_num].cpu().numpy(), # baseOrientation=xyzw.cpu().numpy()) show_max_num_retries_per_goal = 10 for i, q in enumerate(sol.solutions[0]): if i > show_max_num_retries_per_goal: break for dof in range(q.shape[0]): p.resetJointState(armId, dof, q[dof]) input("Press enter to continue") # p.removeBody(goalId) while True: p.stepSimulation()