Source code for concepts.dm.crowhat.manipulation_utils.operation_space_trajectory
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
# File : operation_space_trajectory.py
# Author : Jiayuan Mao
# Email : maojiayuan@gmail.com
# Date : 07/23/2024
#
# This file is part of Project Concepts.
# Distributed under terms of the MIT license.
import numpy as np
from typing import Sequence, Tuple, NamedTuple
from concepts.utils.typing_utils import VecNf, Vec3f, Vec4f
from concepts.math.interpolation_utils import PoseSpline
from concepts.dm.crowhat.manipulation_utils.manipulator_interface import GeneralArmArmMotionPlanningInterface, MotionPlanningResult
from concepts.dm.crowhat.manipulation_utils.pose_utils import pose_distance
[docs]
class OperationSpaceTrajectory(NamedTuple):
qpos_trajectory: Sequence[VecNf]
pose_trajectory: Sequence[Tuple[Vec3f, Vec4f]]
[docs]
def gen_joint_trajectory_from_cartesian_path_with_differential_ik(
arm: GeneralArmArmMotionPlanningInterface,
start_qpos: VecNf,
cartesian_path: Sequence[Tuple[Vec3f, Vec4f]],
step_size: float = 0.01,
target_tolerance: float = 0.01
):
qpos = np.asarray(start_qpos)
pose_spline = PoseSpline.from_pose_sequence(cartesian_path)
goal_pose = cartesian_path[-1]
qpos_trajectory = [qpos]
pose_trajectory = [cartesian_path[0]]
assert pose_distance(pose_trajectory[0], arm.fk(qpos)) < 1e-3, f'The start qpos does not match the start pose: {pose_trajectory[0]} vs {arm.fk(qpos)}'
solved = False
for i in range(1000):
last_qpos, last_pose = qpos_trajectory[-1], pose_trajectory[-1]
if pose_distance(last_pose, goal_pose) < target_tolerance:
solved = True
break
_, next_pose_target = pose_spline.get_next(last_pose, step_size=1)
dq = arm.differential_ik_qpos_diff(last_qpos, last_pose, next_pose_target)
next_qpos = last_qpos + dq / np.linalg.norm(dq) * step_size
qpos_trajectory.append(next_qpos)
pose_trajectory.append(arm.fk(next_qpos))
progress = pose_distance(last_pose, pose_trajectory[-1])
if progress < 1e-6:
return MotionPlanningResult.fail(f'No progress made at step {i}. Current progress: {progress}.')
if not solved:
return MotionPlanningResult.fail('Failed to reach the goal pose after 1000 steps.')
return MotionPlanningResult.success(OperationSpaceTrajectory(qpos_trajectory, pose_trajectory))