Files

694 lines
30 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import copy
import json
import os
from sqlite3 import dbapi2
from this import d
import time
from pyboot.utils.log import Log
import trimesh
curPath = os.path.abspath(os.path.dirname(__file__))
rootPath = os.path.split(curPath)[0]
import numpy as np
from data_gen_dependencies.transforms import calculate_rotation_matrix, rotate_around_axis
from data_gen_dependencies.object import OmniObject, transform_coordinates_3d
from data_gen_dependencies.fix_rotation import rotate_along_axis
from data_gen_dependencies.action import build_stage
from scipy.interpolate import interp1d
from scipy.spatial.transform import Rotation as R
def draw_axis(robot, pose):
if pose.shape[0] == 4 and pose.shape[1] == 4:
pose = np.concatenate([pose[:3, 3], R.from_matrix(pose[:3, :3]).as_euler('xyz')])
def generate_orthogonal_lines(point, angles, scale):
assert len(point) == 3 and len(angles) == 3
# Define rotation matrices for each axis
Rx = np.array([[1, 0, 0],
[0, np.cos(angles[0]), -np.sin(angles[0])],
[0, np.sin(angles[0]), np.cos(angles[0])]])
Ry = np.array([[np.cos(angles[1]), 0, np.sin(angles[1])],
[0, 1, 0],
[-np.sin(angles[1]), 0, np.cos(angles[1])]])
Rz = np.array([[np.cos(angles[2]), -np.sin(angles[2]), 0],
[np.sin(angles[2]), np.cos(angles[2]), 0],
[0, 0, 1]])
# Combined rotation matrix
R = Rz @ Ry @ Rx
# Define the unit vectors for the axes
unit_vectors = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
# Rotate the unit vectors
rotated_vectors = R @ unit_vectors.T
# Draw the lines
lines = []
for vec in rotated_vectors.T:
start_point = point
end_point = point + vec * scale
lines.append(np.concatenate([start_point, end_point]))
return np.stack(lines)
draw_colors = [
[0, 0, 1],
[0, 1, 0],
[1, 0, 0],
]
line_sizes = [1, 1, 1]
xyz_axis = generate_orthogonal_lines(point=pose[:3], angles=pose[3:], scale=0.1)
start_point = xyz_axis[:, :3]
end_point = xyz_axis[:, 3:]
robot.client.DrawLine(start_point, end_point, draw_colors, line_sizes)
def load_gripper_width_interp_func(file):
data = json.load(open(file, 'r'))
digits = []
widths = []
depths = []
for frame in data:
digits.append(frame["angel"])
widths.append(frame["width"])
depths.append(frame["depth"])
digits = np.array(digits)
widths = np.array(widths)
depths = np.array(depths)
func_width2depth = interp1d(widths, depths, kind="linear", fill_value="extrapolate")
return func_width2depth
func_width2depth = load_gripper_width_interp_func(os.path.dirname(__file__) + "/gripper_width_120s_fixed.json")
def format_object(obj, distance, type='active'):
if obj is None:
return None
xyz, direction = obj.xyz, obj.direction
direction = direction / np.linalg.norm(direction) * distance
type = type.lower()
if type == 'active':
xyz_start = xyz
xyz_end = xyz_start + direction
elif type == 'passive' or type == 'plane':
xyz_end = xyz
xyz_start = xyz_end - direction
part2obj = np.eye(4)
part2obj[:3, 3] = xyz_start
obj.obj2part = np.linalg.inv(part2obj)
obj_info = {
'pose': obj.obj_pose,
'length': obj.obj_length,
'xyz_start': xyz_start,
'xyz_end': xyz_end,
'obj2part': obj.obj2part
}
return obj_info
def obj2world(obj_info):
obj_pose = obj_info['pose']
obj_length = obj_info['length']
obj2part = obj_info['obj2part']
xyz_start = obj_info['xyz_start']
xyz_end = obj_info['xyz_end']
arrow_in_obj = np.array([xyz_start, xyz_end]).transpose(1, 0)
arrow_in_world = transform_coordinates_3d(arrow_in_obj, obj_pose).transpose(1, 0)
xyz_start_world, xyz_end_world = arrow_in_world
direction_world = xyz_end_world - xyz_start_world
direction_world = direction_world / np.linalg.norm(direction_world)
obj_info_world = {
'pose': obj_pose,
'length': obj_length,
'obj2part': obj2part,
'xyz_start': xyz_start_world,
'xyz_end': xyz_end_world,
'direction': direction_world,
}
return obj_info_world
def get_aligned_fix_pose(active_obj, passive_obj, distance=0.01, N=1):
try:
active_object = format_object(active_obj, type='active', distance=distance)
passive_object = format_object(passive_obj, type='passive', distance=distance)
except:
print('error')
active_obj_world = obj2world(active_object)
current_obj_pose = active_obj_world['pose']
if passive_object is None:
return current_obj_pose[np.newaxis, ...]
passive_obj_world = obj2world(passive_object)
passive_obj_world['direction'] = passive_obj.direction
R = calculate_rotation_matrix(active_obj_world['direction'], passive_obj_world['direction'])
T = passive_obj_world['xyz_end'] - R @ active_obj_world['xyz_start']
transform_matrix = np.eye(4)
transform_matrix[:3, :3] = R
transform_matrix[:3, 3] = T
target_obj_pose = transform_matrix @ current_obj_pose
target_obj_pose[:3, 3] = passive_obj.obj_pose[:3, 3]
poses = []
for angle in [i * 360 / N for i in range(N)]:
pose_rotated = rotate_around_axis(
target_obj_pose,
passive_obj_world['xyz_start'],
passive_obj_world['direction'],
angle)
poses.append(pose_rotated)
return np.stack(poses)
def get_aligned_pose(active_obj, passive_obj, distance=0.01, N=1):
try:
active_object = format_object(active_obj, type='active', distance=distance)
passive_object = format_object(passive_obj, type='passive', distance=distance)
except:
print('error')
active_obj_world = obj2world(active_object)
current_obj_pose = active_obj_world['pose']
if passive_object is None:
return current_obj_pose[np.newaxis, ...]
passive_obj_world = obj2world(passive_object)
R = calculate_rotation_matrix(active_obj_world['direction'], passive_obj_world['direction'])
T = passive_obj_world['xyz_end'] - R @ active_obj_world['xyz_start']
transform_matrix = np.eye(4)
transform_matrix[:3, :3] = R
transform_matrix[:3, 3] = T
target_obj_pose = transform_matrix @ current_obj_pose
poses = []
for angle in [i * 360 / N for i in range(N)]:
pose_rotated = rotate_around_axis(
target_obj_pose,
passive_obj_world['xyz_start'],
passive_obj_world['direction'],
angle)
poses.append(pose_rotated)
return np.stack(poses)
def load_task_solution(task_info):
Log.info('Loading task solution')
# task_info = json.load(open('%s/task_info.json'%task_dir, 'rb'))
stages = task_info['stages']
objects = {
'gripper': OmniObject('gripper')
}
for i, obj_info in enumerate(task_info['objects']):
Log.info(f'Loading object: {obj_info["object_id"]} [Loading task solution: {i+1}/{len(task_info["objects"])}]')
obj_id = obj_info['object_id']
if obj_id == 'fix_pose':
obj = OmniObject('fix_pose')
if 'position' not in obj_info or 'direction' not in obj_info:
print(f"Error: Missing position/direction in object {obj_id}")
continue
obj.set_pose(np.array(obj_info['position']), np.array([0.001, 0.001, 0.001]))
obj.elements = {
'active': {},
'passive': {
'place': {
'default': [
{
'xyz': np.array([0, 0, 0]),
'direction': np.array(obj_info['direction'])
}
]
}
}
}
objects[obj_id] = obj
else:
obj_dir = obj_info["data_info_dir"]
obj = OmniObject.from_obj_dir(obj_dir, obj_info=obj_info)
objects[obj_id] = obj
if obj.is_articulated:
for part_id in obj.parts_info:
id = obj_id + '/%s' % part_id
objects[id] = copy.deepcopy(obj)
objects[id].name = id
objects[id].size = obj.parts_info[part_id]['size']
joint_name = obj.parts_info[part_id]['correspond_joint_id']
objects[id].joint_name = joint_name
if objects[id].joint_name is not None and joint_name in obj.joints_info:
objects[id].joint_type = obj.joints_info[joint_name]['joint_type']
objects[id].joint_axis = obj.joints_info[joint_name]['joint_axis']
objects[id].lower_bound = obj.joints_info[joint_name]['lower_bound']
objects[id].upper_bound = obj.joints_info[joint_name]['upper_bound']
if len(obj.parts_info):
del objects[obj_id]
Log.success('Finished Loading task solution')
return stages, objects
def parse_stage(stage, objects):
action = stage['action']
if action in ['reset']:
return action, 'gripper', 'gripper', None, None, None, None
active_obj_id = stage['active']['object_id']
if 'part_id' in stage['active']:
active_obj_id += '/%s' % stage['active']['part_id']
passive_obj_id = stage['passive']['object_id']
if 'part_id' in stage['passive']:
passive_obj_id += '/%s' % stage['passive']['part_id']
active_obj = objects[active_obj_id]
passive_obj = objects[passive_obj_id]
single_obj = action in ['pull', 'rotate', 'slide', 'shave', 'brush', 'wipe', 'pull_revolute', "twist"]
def _load_element(obj, type):
if action in ['pick', 'hook']:
action_mapped = 'grasp'
elif action in ['pull_revolute']:
action_mapped = 'pull'
elif action in ['push_revolute']:
action_mapped = 'push'
elif action in ["press_prismatic"]:
action_mapped = 'press'
else:
action_mapped = action
if (action_mapped == 'grasp' or action_mapped == 'pull') and type == 'active':
return None, None
elif obj.name == 'gripper':
element = obj.elements[type][action_mapped]
return element, 'default'
primitive = stage[type]['primitive'] if stage[type]['primitive'] is not None else 'default'
if primitive != 'default' or (action_mapped == 'grasp' and type == 'passive'):
if action_mapped not in obj.elements[type] and action not in obj.elements[type]:
#======= DEBUG START =======
print(f'debug: ')
import ipdb;ipdb.set_trace()
#======= DEBUG END =======
print('No %s element for %s' % (action_mapped, obj.name))
return None, None
elif action_mapped in obj.elements[type]:
element = obj.elements[type][action_mapped][primitive]
elif action in obj.elements[type]:
element = obj.elements[type][action][primitive]
else:
element = []
for primitive in obj.elements[type][action_mapped]:
_element = obj.elements[type][action_mapped][primitive]
if isinstance(_element, list):
element += _element
else:
element.append(_element)
return element, primitive
passive_element, passive_primitive = _load_element(passive_obj, 'passive')
if not single_obj:
active_element, active_primitive = _load_element(active_obj, 'active')
else:
active_element, active_primitive = passive_element, passive_primitive
return action, active_obj_id, passive_obj_id, active_element, passive_element, active_primitive, passive_primitive
def select_obj(objects, stages, robot):
gripper2obj = None
extra_params = stages[0].get('extra_params', {})
arm = extra_params.get('arm', 'right')
current_gripper_pose = robot.get_ee_pose(id=arm)
''' 初筛抓取pose,得到 grasp_poses_canonical, grasp_poses '''
grasp_stage_id = None
if stages[0]['action'] in ['push', 'reset', 'press_prismatic']:
gripper2obj = current_gripper_pose
elif stages[0]['action'] in ['pick', 'grasp', 'hook', "pull_revolute", "twist", "push_revolute"]:
action = stages[0]['action']
''' 筛掉无IK解的grasp pose '''
grasp_stage_id = 0
grasp_stage = parse_stage(stages[0], objects)
_, _, passive_obj_id, _, passive_element, _, _ = grasp_stage
grasp_obj_id = passive_obj_id
if stages[0]['action'] == "pull_revolute":
import ipdb;ipdb.set_trace()
if stages[0]['action'] == "push_revolute":
import ipdb;ipdb.set_trace()
grasp_poses_canonical = passive_element['grasp_pose'].copy()
grasp_widths = passive_element['width']
grasp_poses_canonical[:, :3, :3] = grasp_poses_canonical[:, :3, :3] @ robot.robot_gripper_2_grasp_gripper[
np.newaxis, ...]
grasp_poses_canonical_flip = []
for _i in range(grasp_poses_canonical.shape[0]):
grasp_poses_canonical_flip.append(rotate_along_axis(grasp_poses_canonical[_i], 180, 'z', use_local=True))
grasp_poses_canonical_flip = np.stack(grasp_poses_canonical_flip)
grasp_poses_canonical = np.concatenate([grasp_poses_canonical, grasp_poses_canonical_flip], axis=0)
grasp_widths = np.concatenate([grasp_widths, grasp_widths], axis=0)
grasp_poses = objects[passive_obj_id].obj_pose[np.newaxis, ...] @ grasp_poses_canonical
# filter with IK-checking
ik_success, _ = robot.solve_ik(grasp_poses, ee_type='gripper', arm=arm, type='Simple')
grasp_poses_canonical, grasp_poses = grasp_poses_canonical[ik_success], grasp_poses[ik_success]
grasp_widths = grasp_widths[ik_success]
if len(grasp_poses) == 0:
print(action, 'No grasp_gripper_pose can pass Isaac IK')
return []
''' 基于有IK解的grasp pose分数,选择最优的passive primitive element,同时选出最优的一个grasp pose'''
if grasp_stage_id is not None:
next_stage_id = grasp_stage_id + 1
if next_stage_id < len(stages):
action, active_obj_id, passive_obj_id, active_elements, passive_elements, active_primitive, passive_primitive = parse_stage(
stages[next_stage_id], objects)
single_obj = active_obj_id == passive_obj_id
active_obj = objects[active_obj_id]
passive_obj = objects[passive_obj_id]
passive_element = passive_elements[np.random.choice(len(passive_elements))]
if action == 'place': # TODO A2D暂时这样搞Franka要取消
# import ipdb; ipdb.set_trace()
obj_pose = active_obj.obj_pose
mesh = trimesh.load(active_obj.info['mesh_file'], force="mesh")
mesh.apply_scale(0.001)
mesh.apply_transform(obj_pose)
pts, _ = trimesh.sample.sample_surface(mesh, 200) # 表面采样
xyz = np.array([np.mean(pts[:, 0]), np.mean(pts[:, 1]), np.percentile(pts[:, 2], 1)])
direction = np.array([0, 0, -1])
xyz_canonical = (np.linalg.inv(obj_pose) @ np.array([*xyz, 1]))[:3]
direction_canonical = (np.linalg.inv(obj_pose) @ np.array([*direction, 0]))[:3]
active_elements = [{'xyz': xyz_canonical, 'direction': direction_canonical}]
#import ipdb; ipdb.set_trace()
t0 = time.time()
element_ik_score = []
grasp_pose_ik_score = []
for active_element in active_elements:
# interaction between two rigid objects
obj_pose = active_obj.obj_pose
N_align = 12
if not single_obj:
active_obj.xyz, active_obj.direction = active_element['xyz'], active_element['direction']
if passive_obj_id == 'fix_pose':
passive_obj.xyz, passive_obj.direction = passive_element['xyz'], passive_element['direction']
target_obj_poses = get_aligned_fix_pose(active_obj, passive_obj, N=N_align)
else:
passive_obj.xyz, passive_obj.direction = passive_element['xyz'], passive_element['direction']
target_obj_poses = get_aligned_pose(active_obj, passive_obj, N=N_align)
else: # 物体自身移动
transform = np.eye(4)
transform[:3, 3] = active_element['xyz']
target_obj_poses = (obj_pose @ transform)[np.newaxis, ...]
N_align = 1
N_obj_pose = target_obj_poses.shape[0]
N_grasp_pose = grasp_poses_canonical.shape[0]
target_gripper_poses = (
target_obj_poses[:, np.newaxis, ...] @ grasp_poses_canonical[np.newaxis, ...]).reshape(-1,
4, 4)
ik_success, _ = robot.solve_ik(target_gripper_poses, ee_type='gripper', type='Simple', arm=arm)
element_ik_score.append(np.max(ik_success.reshape(N_obj_pose, N_grasp_pose).sum(axis=1)))
grasp_pose_ik = ik_success.reshape(N_obj_pose, N_grasp_pose)
grasp_pose_ik_score.append(np.sum(grasp_pose_ik, axis=0))
# print("ik solve time: ", time.time() - t0)
best_element_id = np.argmax(element_ik_score)
best_active_element = active_elements[best_element_id]
if not single_obj:
active_obj.elements['active'][action] = {active_primitive: best_active_element}
grasp_ik_score = grasp_pose_ik_score[best_element_id]
# import ipdb;ipdb.set_trace()
_mask = grasp_ik_score >= np.median(grasp_ik_score) / 2
best_grasp_poses = grasp_poses[_mask]
# downsample grasp pose
downsample_num = 100
grasps_num = best_grasp_poses.shape[0]
selected_index = np.random.choice(grasps_num, size=min(downsample_num, grasps_num), replace=False)
best_grasp_poses = best_grasp_poses[selected_index]
# if best_grasp_poses.shape[0] > downsample_num:
# best_grasp_poses = best_grasp_poses[:downsample_num]
if best_grasp_poses.shape[0] > 1:
joint_names = robot.joint_names[arm]
ik_success, ik_info = robot.solve_ik(best_grasp_poses, ee_type='gripper', type='Simple', arm=arm)
best_grasp_poses = best_grasp_poses[ik_success]
ik_joint_positions = ik_info["joint_positions"][ik_success]
ik_joint_names = ik_info["joint_names"][ik_success]
ik_jacobian_score = ik_info["jacobian_score"][ik_success]
if len(best_grasp_poses) == 0:
print(action, 'No best_grasp_poses can pass curobo IK')
return []
target_joint_positions = []
for ik_joint_position, ik_joint_name in zip(ik_joint_positions, ik_joint_names):
temp_target_joint_positions = []
for joint_name in joint_names:
temp_target_joint_positions.append(ik_joint_position[list(ik_joint_name).index(joint_name)])
target_joint_positions.append(np.array(temp_target_joint_positions))
target_joint_positions = np.array(target_joint_positions)
# choose target pose based on the ik jacobian score and ik joint positions
cur_joint_states = robot.client.get_joint_positions().states
cur_joint_positions = []
for key in cur_joint_states:
if key.name in joint_names:
cur_joint_positions.append(key.position)
cur_joint_positions = np.array(cur_joint_positions)
joint_pos_dist = np.linalg.norm(target_joint_positions - cur_joint_positions[np.newaxis, :], axis=1)
# joint_pos_dist = (joint_pos_dist - np.min(joint_pos_dist))/(np.max(joint_pos_dist) - np.min(joint_pos_dist))
# ik_jacobian_score = (ik_jacobian_score - np.min(ik_jacobian_score))/(np.max(ik_jacobian_score) - np.min(ik_jacobian_score))
cost = joint_pos_dist # - ik_jacobian_score
idx_sorted = np.argsort(cost)
best_grasp_pose = best_grasp_poses[idx_sorted][0]
else:
best_grasp_pose = best_grasp_poses[0]
best_grasp_pose_canonical = np.linalg.inv(objects[grasp_obj_id].obj_pose) @ best_grasp_pose
gripper2obj = best_grasp_pose_canonical
else:
gripper2obj = grasp_poses_canonical[0]
return gripper2obj
def split_grasp_stages(stages):
split_stages = []
i = 0
while i < len(stages):
if stages[i]['action'] in ['pick', 'grasp', 'hook']:
if (i + 1) < len(stages) and stages[i + 1]['action'] not in ['pick', 'grasp', 'hook']:
split_stages.append([stages[i], stages[i + 1]])
i += 2
else:
split_stages.append([stages[i]])
i += 1
else:
split_stages.append([stages[i]])
i += 1
return split_stages
def generate_action_stages(objects, all_stages, robot):
split_stages = split_grasp_stages(all_stages)
action_stages = []
for stages in split_stages:
gripper2obj = select_obj(objects, stages, robot)
if gripper2obj is None or len(gripper2obj) == 0:
print('No gripper2obj pose can pass IK')
gripper2obj = select_obj(objects, stages, robot)
return []
stage_idx = 0
for stage in stages:
stage_idx += 1
extra_params = stage.get('extra_params', {})
arm = extra_params.get('arm', 'right')
action, active_obj_id, passive_obj_id, active_elements, passive_elements, active_primitive, passive_primitive = parse_stage(
stage, objects)
active_obj = objects[active_obj_id]
passive_obj = objects[passive_obj_id]
Log.info(f'Generating action stage [{stage_idx}/{len(stages)}]: Action({action}), Active Object({active_obj_id}), Passive Object({passive_obj_id})')
substages = None
#======= DEBUG START =======
print(f'debug: before build_stage {action}')
#import ipdb;ipdb.set_trace()
#======= DEBUG END =======
if action in ['reset']:
substages = True
elif action in ['pick', 'grasp', 'hook']:
substages = build_stage(action)(active_obj_id, passive_obj_id, active_elements, passive_elements,
gripper2obj, extra_params=stage.get('extra_params', None), objects=objects)
elif action in ['slide', 'shave', 'brush', 'wipe', 'pull', 'rotate', 'move',
'reset', "pull_revolute","push_revolute", "twist"]: # grasp + 物体自身运动
passive_element = passive_elements[np.random.choice(len(passive_elements))]
substages = build_stage(action)(
active_obj_id=active_obj_id,
passive_obj_id=passive_obj_id,
passive_element=passive_element,
objects=objects,
target_pose=gripper2obj
)
else:
passive_element = passive_elements[np.random.choice(len(passive_elements))]
# active_element = active_elements[np.random.choice(len(active_elements))] if isinstance(active_elements, list) else active_elements
if not isinstance(active_elements, list):
active_elements = [active_elements]
for active_element in active_elements:
joint_names = robot.joint_names[arm]
# interaction between two rigid objects
obj_pose = active_obj.obj_pose
anchor_pose = passive_obj.obj_pose
current_obj_pose_canonical = np.linalg.inv(anchor_pose) @ obj_pose
active_obj.xyz, active_obj.direction = active_element['xyz'], active_element['direction']
passive_obj.xyz, passive_obj.direction = passive_element['xyz'], passive_element['direction']
if active_obj.name == 'gripper':
gripper2obj = np.eye(4)
if passive_obj_id == 'fix_pose':
# import ipdb;ipdb.set_trace()
target_obj_poses = get_aligned_fix_pose(active_obj, passive_obj, N=18)
else:
target_obj_poses = get_aligned_pose(active_obj, passive_obj, N=18)
target_gripper_poses = target_obj_poses @ gripper2obj[np.newaxis, ...]
# import ipdb;ipdb.set_trace()
# downsample target_gripper_poses
downsample_num = 100
if target_gripper_poses.shape[0] > downsample_num:
target_gripper_poses = target_gripper_poses[:downsample_num]
ik_success, ik_info = robot.solve_ik(target_gripper_poses, ee_type='gripper', type='AvoidObs',
arm=arm)
target_gripper_poses_pass_ik = target_gripper_poses[ik_success]
ik_joint_positions = ik_info["joint_positions"][ik_success]
ik_joint_names = ik_info["joint_names"][ik_success]
ik_jacobian_score = ik_info["jacobian_score"][ik_success]
if len(target_gripper_poses_pass_ik) == 0:
Log.warning(f'{action}: No target_obj_pose can pass isaac curobo IK')
import ipdb;ipdb.set_trace()
continue
target_joint_positions = []
for ik_joint_position, ik_joint_name in zip(ik_joint_positions, ik_joint_names):
temp_target_joint_positions = []
for joint_name in joint_names:
temp_target_joint_positions.append(ik_joint_position[list(ik_joint_name).index(joint_name)])
target_joint_positions.append(np.array(temp_target_joint_positions))
target_joint_positions = np.array(target_joint_positions)
# choose target pose based on the jacobian score and ik joint positions difference
cur_joint_states = robot.client.get_joint_positions().states
cur_joint_positions = []
for key in cur_joint_states:
if key.name in joint_names:
cur_joint_positions.append(key.position)
cur_joint_positions = np.array(cur_joint_positions)
joint_pos_dist = np.linalg.norm(target_joint_positions - cur_joint_positions[np.newaxis, :], axis=1)
# joint_pos_dist = (joint_pos_dist - np.min(joint_pos_dist))/(np.max(joint_pos_dist) - np.min(joint_pos_dist))
# ik_jacobian_score = (ik_jacobian_score - np.min(ik_jacobian_score))/(np.max(ik_jacobian_score) - np.min(ik_jacobian_score))
cost = joint_pos_dist # - ik_jacobian_score
idx_sorted = np.argsort(cost)
best_target_gripper_pose = target_gripper_poses_pass_ik[idx_sorted][0]
best_target_obj_pose = best_target_gripper_pose @ np.linalg.inv(gripper2obj)
target_obj_pose_canonical = np.linalg.inv(
anchor_pose) @ best_target_obj_pose # TODO 暂时只取一个可行解后面要结合grasp pose做整条trajectory的joint solve
part2obj = np.eye(4)
part2obj[:3, 3] = active_obj.xyz
obj2part = np.linalg.inv(part2obj)
substages = build_stage(action)(
active_obj_id=active_obj_id,
passive_obj_id=passive_obj_id,
target_pose=target_obj_pose_canonical,
current_pose=current_obj_pose_canonical,
obj2part=obj2part,
vector_direction=passive_element['direction'],
passive_element=passive_element,
extra_params=stage.get('extra_params', {}),
objects=objects
)
break
if substages is None:
Log.warning(f'{action}:substage is None')
return []
action_stages.append((action, substages))
return action_stages
def solve_target_gripper_pose(stage, objects):
active_obj_ID, passive_obj_ID, target_pose_canonical, gripper_action, transform_world, motion_type = stage
anchor_pose = objects[passive_obj_ID].obj_pose
if motion_type == 'Trajectory':
assert len(target_pose_canonical.shape) == 3, 'The target_pose should be a list of poses'
target_pose = anchor_pose[np.newaxis, ...] @ target_pose_canonical
target_pose = transform_world[np.newaxis, ...] @ target_pose
else:
target_pose = anchor_pose @ target_pose_canonical
target_pose = transform_world @ target_pose
assert 'gripper' in objects, 'The gripper should be the first one in the object list'
current_gripper_pose = objects['gripper'].obj_pose
if active_obj_ID == 'gripper':
target_gripper_pose = target_pose
else:
current_obj_pose = objects[active_obj_ID].obj_pose
gripper2obj = np.linalg.inv(current_obj_pose) @ current_gripper_pose
if len(target_pose.shape) == 3:
gripper2obj = gripper2obj[np.newaxis, ...]
target_obj_pose = target_pose
target_gripper_pose = target_obj_pose @ gripper2obj
return target_gripper_pose