finshi press action

This commit is contained in:
2025-09-24 11:11:24 +08:00
parent 8b89b2e35b
commit 330d903047
16 changed files with 296 additions and 91 deletions

View File

@@ -4,7 +4,9 @@ from .insert import InsertStage, HitStage
from .slide import SlideStage from .slide import SlideStage
from .pour import PourStage from .pour import PourStage
from .pull import PullStage from .pull import PullStage
from .push import PushStage, ClickStage from .push import PushStage
from .pull_revolute import PullRevoluteStage
from .press import PressPrismaticStage
ACTION_STAGE = { ACTION_STAGE = {
"grasp": GraspStage, "grasp": GraspStage,
@@ -19,9 +21,11 @@ ACTION_STAGE = {
"hit": NotImplemented, "hit": NotImplemented,
"pour": PourStage, "pour": PourStage,
"push": PushStage, "push": PushStage,
'click': ClickStage, 'click': PressPrismaticStage,
'touch': ClickStage, 'touch': PressPrismaticStage,
"pull": PullStage 'press_prismatic': PressPrismaticStage,
"pull": PullStage,
"pull_revolute": PullRevoluteStage,
} }
def build_stage(action): def build_stage(action):

View File

@@ -27,7 +27,6 @@ def simple_check_completion(goal, objects, last_statement=None, pos_threshold=0.
def solve_target_gripper_pose(stage, objects): def solve_target_gripper_pose(stage, objects):
active_obj_ID, passive_obj_ID, target_pose_canonical, gripper_action, transform_world, motion_type = stage active_obj_ID, passive_obj_ID, target_pose_canonical, gripper_action, transform_world, motion_type = stage
anchor_pose = objects[passive_obj_ID].obj_pose anchor_pose = objects[passive_obj_ID].obj_pose

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate, simple_check_comple
class PickStage(StageTemplate): class PickStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element, passive_element, grasp_pose, extra_params=None, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element, passive_element, grasp_pose, extra_params=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.grasp_pose_canonical = grasp_pose self.grasp_pose_canonical = grasp_pose
self.use_pre_grasp = False self.use_pre_grasp = False
@@ -104,6 +104,7 @@ class GraspStage(PickStage):
self.sub_stages.append([pre_grasp_pose, None, np.eye(4), motion_type]) self.sub_stages.append([pre_grasp_pose, None, np.eye(4), motion_type])
# sub-stage-1 moveTo grasp pose # sub-stage-1 moveTo grasp pose
self.sub_stages.append([grasp_pose, 'close', np.eye(4), motion_type]) self.sub_stages.append([grasp_pose, 'close', np.eye(4), motion_type])

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate, simple_check_comple
class InsertStage(StageTemplate): class InsertStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, vector_direction=None, extra_params={}, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, vector_direction=None, extra_params={}, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate, simple_check_comple
class PlaceStage(StageTemplate): class PlaceStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, extra_params={}, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, extra_params={}, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pre_transform_up =0.12 self.pre_transform_up =0.12
self.place_transform_up = np.array([0, 0, 0.01]) self.place_transform_up = np.array([0, 0, 0.01])

View File

@@ -9,7 +9,7 @@ import numpy as np
class PourStage(StageTemplate): class PourStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, current_pose=None, obj2part=None, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, current_pose=None, obj2part=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pre_pour_height = 0.25 self.pre_pour_height = 0.25

View File

@@ -0,0 +1,34 @@
import numpy as np
from data_gen_dependencies.action.base import StageTemplate
class PressPrismaticStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, vector_direction=None,active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pre_distance = -0.03
self.passive_obj = passive_obj
self.active_obj = active_obj
self.joint_position_threshold = passive_element.get('joint_position_threshold', 0.7)
self.joint_position_threshold = self.joint_position_threshold if self.joint_position_threshold is not None else 0.7
self.correspond_joint_id = passive_element.get('correspond_joint_id', None)
correspond_joint_info = passive_obj.joints_info[self.correspond_joint_id]
self.joint_lower_limit = correspond_joint_info["lower_bound"]
self.joint_upper_limit = correspond_joint_info["upper_bound"]
self.move_distance = -0.005 + abs(self.joint_lower_limit - self.joint_upper_limit) * self.joint_position_threshold
self.joint_axis = correspond_joint_info["joint_axis"]
self.joint_type = correspond_joint_info["joint_type"]
assert self.joint_type == 'prismatic', "joint_type must be prismatic for press action"
correspond_joint_info = passive_obj.joints_info[self.correspond_joint_id]
self.generate_substage(target_pose, vector_direction)
def generate_substage(self, target_pose, vector_direction):
vector_direction = vector_direction / np.linalg.norm(vector_direction)
pre_pose = target_pose.copy()
pre_pose[:3,3] += vector_direction * self.pre_distance
self.sub_stages.append([pre_pose, 'close', np.eye(4), 'AvoidObs'])
move_pose = target_pose.copy()
move_pose[:3,3] += vector_direction * self.move_distance
self.sub_stages.append([move_pose, None, np.eye(4), 'Simple'])

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate
class PullStage(StageTemplate): class PullStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), extra_params=None, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), extra_params=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pull_distance = passive_element['distance'] self.pull_distance = passive_element['distance']
assert self.pull_distance > 0 assert self.pull_distance > 0
@@ -33,8 +33,6 @@ class PullStage(StageTemplate):
self.sub_stages.append([free_delta_pose, None, np.eye(4), 'local_gripper']) self.sub_stages.append([free_delta_pose, None, np.eye(4), 'local_gripper'])
def check_completion(self, objects): def check_completion(self, objects):
if self.__len__()==0: if self.__len__()==0:
return True return True

View File

@@ -0,0 +1,110 @@
import numpy as np
from data_gen_dependencies.action.base import StageTemplate
class PullRevoluteStage(StageTemplate):
DELTA_DISTANCE = 0.005 # meter
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), extra_params=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
#======= DEBUG START =======
print(f'debug: PullRevoluteStage init')
import ipdb;ipdb.set_trace()
#======= DEBUG END =======
self.passive_obj = passive_obj
self.active_obj = active_obj
self.joint_position_threshold = passive_element.get('joint_position_threshold', 0.7)
self.correspond_joint_id = passive_element.get('correspond_joint_id', None)
correspond_joint_info = passive_obj.joints_info[self.correspond_joint_id]
self.joint_lower_limit = correspond_joint_info["lower_bound"]
self.joint_upper_limit = correspond_joint_info["upper_bound"]
self.joint_axis = correspond_joint_info["joint_axis"]
self.joint_type = correspond_joint_info["joint_type"]
assert self.joint_type == 'revolute', "joint_type must be revolute for pull_revolute action"
self.revolute_radius = passive_element.get('revolute_radius', None)
assert self.revolute_radius is not None, "revolute_radius is required for pull_revolute action"
if self.joint_position_threshold is None:
self.joint_position_threshold = 0.7
assert self.joint_position_threshold >= 0 and self.joint_position_threshold <= 1
self.joint_direction = passive_element.get('joint_direction', 1)
assert self.joint_direction in [-1, 1]
self.joint_velocity_threshold = passive_element.get('joint_velocity_threshold', 999)
vector_direction = passive_element['direction']
self.extra_params = {} if extra_params is None else extra_params
self.generate_substage(target_pose, vector_direction)
def generate_substage(self, target_pose, vector_direction):
vector_direction = vector_direction / np.linalg.norm(vector_direction)
#trajectory = self.test_generate_trajectory(vector_direction)
#trajectory = self.test_generate_trajectory(vector_direction)
total_angle = self.joint_position_threshold * (self.joint_upper_limit - self.joint_lower_limit)
arc_length = abs(self.revolute_radius * total_angle)
step = int(arc_length / self.DELTA_DISTANCE)
from pyboot.utils.log import Log
Log.debug(f'PullRevoluteStage: total_angle={total_angle}, arc_length={arc_length}, step={step}')
for i in range(10):
free_delta_pose = np.eye(4)
free_delta_pose[2,3] = -self.DELTA_DISTANCE
self.sub_stages.append([target_pose, None, np.eye(4), 'AvoidObs'])
self.sub_stages.append([free_delta_pose, None, np.eye(4), 'local_gripper'])
self.sub_stages.append([None, "open", np.eye(4), 'Simple'])
free_delta_pose = np.eye(4)
free_delta_pose[2,3] = -self.DELTA_DISTANCE
self.sub_stages.append([free_delta_pose, None, np.eye(4), 'local_gripper'])
def generate_trajectory(self, init_vector_direction):
trajectory = []
#======= DEBUG START =======
print(f'debug: ')
import ipdb;ipdb.set_trace()
#======= DEBUG END =======
total_angle = self.joint_position_threshold * (self.joint_upper_limit - self.joint_lower_limit)
total_angle *= self.joint_direction
arc_length = abs(self.revolute_radius * total_angle)
num_steps = int(np.ceil(arc_length / self.DELTA_DISTANCE))
if num_steps < 1:
num_steps = 1
delta_theta = total_angle / num_steps
rotation_axis = np.array(self.joint_axis)
current_pose = start_pose.copy()
trajectory.append(current_pose)
for i in range(1, num_steps + 1):
angle = i * delta_theta
R = self.axis_angle_to_matrix(rotation_axis, angle)
move_pose = start_pose @ R
trajectory.append(move_pose)
return trajectory
def axis_angle_to_matrix(self, axis, angle):
axis = axis / np.linalg.norm(axis)
K = np.array([[0, -axis[2], axis[1]],
[axis[2], 0, -axis[0]],
[-axis[1], axis[0], 0]])
R = np.eye(3) + np.sin(angle) * K + (1 - np.cos(angle)) * (K @ K)
T = np.eye(4)
T[:3, :3] = R
return T
def check_completion(self, objects):
if self.__len__() == 0:
return True
succ = False
if self.step_id >= 0:
succ = True
if succ:
self.step_id += 1
return succ

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate, pose_difference
class PushStage(StageTemplate): class PushStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), vector_direction=None, extra_params=None, **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), vector_direction=None, extra_params=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
extra_params = {} if extra_params is None else extra_params extra_params = {} if extra_params is None else extra_params
@@ -73,23 +73,5 @@ class PushStage(StageTemplate):
return succ return succ
class ClickStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=None, vector_direction=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pre_distance = -0.03
self.move_distance = 0.00
self.generate_substage(target_pose, vector_direction)
def generate_substage(self, target_pose, vector_direction):
vector_direction = vector_direction / np.linalg.norm(vector_direction)
# moveTo pre-place position
pre_pose = target_pose.copy()
pre_pose[:3,3] += vector_direction * self.pre_distance
self.sub_stages.append([pre_pose, 'close', np.eye(4), 'AvoidObs'])
# insert
move_pose = target_pose.copy()
move_pose[:3,3] += vector_direction * self.move_distance
self.sub_stages.append([move_pose, None, np.eye(4), 'Simple'])

View File

@@ -4,7 +4,7 @@ from data_gen_dependencies.action.base import StageTemplate, pose_difference
class SlideStage(StageTemplate): class SlideStage(StageTemplate):
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), **kwargs): def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element) super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.pre_distance = 0.0 self.pre_distance = 0.0

View File

@@ -0,0 +1,52 @@
import numpy as np
from data_gen_dependencies.action.base import StageTemplate
class TwistStage(StageTemplate):
DELTA_DISTANCE = 0.01 # meter
def __init__(self, active_obj_id, passive_obj_id, active_element=None, passive_element=None, target_pose=np.eye(4), extra_params=None, active_obj=None, passive_obj=None, **kwargs):
super().__init__(active_obj_id, passive_obj_id, active_element, passive_element)
self.passive_obj = passive_obj
self.active_obj = active_obj
self.joint_position_threshold = passive_element.get('joint_position_threshold', 0.7)
self.correspond_joint_id = passive_element.get('correspond_joint_id', None)
correspond_joint_info = passive_obj.joints_info[self.correspond_joint_id]
self.joint_lower_limit = correspond_joint_info["lower_bound"]
self.joint_upper_limit = correspond_joint_info["upper_bound"]
self.joint_axis = correspond_joint_info["joint_axis"]
self.joint_type = correspond_joint_info["joint_type"]
assert self.joint_type == 'revolute', "joint_type must be revolute for pull_revolute action"
self.revolute_radius = passive_element.get('revolute_radius', None)
assert self.revolute_radius is not None, "revolute_radius is required for pull_revolute action"
if self.joint_position_threshold is None:
self.joint_position_threshold = 0.7
assert self.joint_position_threshold >= 0 and self.joint_position_threshold <= 1
self.joint_direction = passive_element.get('joint_direction', 1)
assert self.joint_direction in [-1, 1]
self.joint_velocity_threshold = passive_element.get('joint_velocity_threshold', 999)
vector_direction = passive_element['direction']
self.extra_params = {} if extra_params is None else extra_params
self.generate_substage(target_pose, vector_direction)
def generate_substage(self, target_pose, vector_direction):
vector_direction = vector_direction / np.linalg.norm(vector_direction)
free_delta_pose = np.eye(4)
free_delta_pose[2,3] = -0.03
self.sub_stages.append([free_delta_pose, None, np.eye(4), 'local_gripper'])
def check_completion(self, objects):
if self.__len__() == 0:
return True
succ = False
if self.step_id >= 0:
succ = True
if succ:
self.step_id += 1
return succ

View File

@@ -3,6 +3,7 @@ import copy
import json import json
import os import os
from sqlite3 import dbapi2 from sqlite3 import dbapi2
from this import d
import time import time
from pyboot.utils.log import Log from pyboot.utils.log import Log
@@ -247,25 +248,30 @@ def load_task_solution(task_info):
obj_dir = obj_info["data_info_dir"] obj_dir = obj_info["data_info_dir"]
obj = OmniObject.from_obj_dir(obj_dir, obj_info=obj_info) obj = OmniObject.from_obj_dir(obj_dir, obj_info=obj_info)
objects[obj_id] = obj objects[obj_id] = obj
if obj.is_articulated:
if hasattr(obj, 'part_ids'): for part_id in obj.parts_info:
for part_id in obj.part_ids:
id = obj_id + '/%s' % part_id id = obj_id + '/%s' % part_id
objects[id] = copy.deepcopy(obj) objects[id] = copy.deepcopy(obj)
objects[id].name = id objects[id].name = id
#====== DEBUG START ====== objects[id].size = obj.parts_info[part_id]['size']
print(f'debug: ') joint_name = obj.parts_info[part_id]['correspond_joint_id']
import ipdb;ipdb.set_trace() objects[id].joint_name = joint_name
#====== DEBUG END ====== if objects[id].joint_name is not None and joint_name in obj.joints_info:
if hasattr(obj, 'part_joint_limits') and obj.part_joint_limits is not None: objects[id].joint_type = obj.joints_info[joint_name]['joint_type']
objects[id].part_joint_limit = obj.part_joint_limits[part_id] objects[id].joint_axis = obj.joints_info[joint_name]['joint_axis']
if len(obj.part_ids): 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] del objects[obj_id]
Log.success('Finished Loading task solution') Log.success('Finished Loading task solution')
return stages, objects return stages, objects
def parse_stage(stage, objects): def parse_stage(stage, objects):
action = stage['action'] action = stage['action']
if action in ['reset']: if action in ['reset']:
return action, 'gripper', 'gripper', None, None, None, None return action, 'gripper', 'gripper', None, None, None, None
@@ -280,24 +286,36 @@ def parse_stage(stage, objects):
active_obj = objects[active_obj_id] active_obj = objects[active_obj_id]
passive_obj = objects[passive_obj_id] passive_obj = objects[passive_obj_id]
single_obj = action in ['pull', 'rotate', 'slide', 'shave', 'brush', 'wipe'] single_obj = action in ['pull', 'rotate', 'slide', 'shave', 'brush', 'wipe', 'pull_revolute']
def _load_element(obj, type): def _load_element(obj, type):
if action in ['pick', 'hook']: if action in ['pick', 'hook']:
action_mapped = 'grasp' action_mapped = 'grasp'
elif action in ['pull_revolute']:
action_mapped = 'pull'
elif action in ["press_prismatic"]:
action_mapped = 'press'
else: else:
action_mapped = action action_mapped = action
if action_mapped == 'grasp' and type == 'active': if (action_mapped == 'grasp' or action_mapped == 'pull') and type == 'active':
return None, None return None, None
elif obj.name == 'gripper': elif obj.name == 'gripper':
element = obj.elements[type][action_mapped] element = obj.elements[type][action_mapped]
return element, 'default' return element, 'default'
primitive = stage[type]['primitive'] if stage[type]['primitive'] is not None else '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 primitive != 'default' or (action_mapped == 'grasp' and type == 'passive'):
if action_mapped not in obj.elements[type]: 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)) print('No %s element for %s' % (action_mapped, obj.name))
return None, None return None, None
elif action_mapped in obj.elements[type]:
element = obj.elements[type][action_mapped][primitive] element = obj.elements[type][action_mapped][primitive]
elif action in obj.elements[type]:
element = obj.elements[type][action][primitive]
else: else:
element = [] element = []
for primitive in obj.elements[type][action_mapped]: for primitive in obj.elements[type][action_mapped]:
@@ -324,11 +342,10 @@ def select_obj(objects, stages, robot):
''' 初筛抓取pose,得到 grasp_poses_canonical, grasp_poses ''' ''' 初筛抓取pose,得到 grasp_poses_canonical, grasp_poses '''
grasp_stage_id = None grasp_stage_id = None
if stages[0]['action'] in ['push', 'reset', 'press_prismatic']:
if stages[0]['action'] in ['push', 'reset', 'click']:
gripper2obj = current_gripper_pose gripper2obj = current_gripper_pose
elif stages[0]['action'] in ['pick', 'grasp', 'hook']: elif stages[0]['action'] in ['pick', 'grasp', 'hook', "pull_revolute"]:
action = stages[0]['action'] action = stages[0]['action']
''' 筛掉无IK解的grasp pose ''' ''' 筛掉无IK解的grasp pose '''
@@ -386,6 +403,7 @@ def select_obj(objects, stages, robot):
direction_canonical = (np.linalg.inv(obj_pose) @ np.array([*direction, 0]))[:3] direction_canonical = (np.linalg.inv(obj_pose) @ np.array([*direction, 0]))[:3]
active_elements = [{'xyz': xyz_canonical, 'direction': direction_canonical}] active_elements = [{'xyz': xyz_canonical, 'direction': direction_canonical}]
# import ipdb; ipdb.set_trace() # import ipdb; ipdb.set_trace()
t0 = time.time() t0 = time.time()
element_ik_score = [] element_ik_score = []
@@ -504,7 +522,6 @@ def split_grasp_stages(stages):
def generate_action_stages(objects, all_stages, robot): def generate_action_stages(objects, all_stages, robot):
split_stages = split_grasp_stages(all_stages) split_stages = split_grasp_stages(all_stages)
action_stages = [] action_stages = []
for stages in split_stages: for stages in split_stages:
gripper2obj = select_obj(objects, stages, robot) gripper2obj = select_obj(objects, stages, robot)
@@ -512,30 +529,37 @@ def generate_action_stages(objects, all_stages, robot):
print('No gripper2obj pose can pass IK') print('No gripper2obj pose can pass IK')
gripper2obj = select_obj(objects, stages, robot) gripper2obj = select_obj(objects, stages, robot)
return [] return []
stage_idx = 0
for stage in stages: for stage in stages:
stage_idx += 1
extra_params = stage.get('extra_params', {}) extra_params = stage.get('extra_params', {})
arm = extra_params.get('arm', 'right') arm = extra_params.get('arm', 'right')
current_gripper_pose = robot.get_ee_pose(id=arm)
action, active_obj_id, passive_obj_id, active_elements, passive_elements, active_primitive, passive_primitive = parse_stage( action, active_obj_id, passive_obj_id, active_elements, passive_elements, active_primitive, passive_primitive = parse_stage(
stage, objects) stage, objects)
active_obj = objects[active_obj_id] active_obj = objects[active_obj_id]
passive_obj = objects[passive_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})')
single_obj = active_obj_id == passive_obj_id
substages = None substages = None
#======= DEBUG START =======
print(f'debug: before build_stage {action}')
#import ipdb;ipdb.set_trace()
#======= DEBUG END =======
if action in ['reset']: if action in ['reset']:
substages = True substages = True
elif action in ['pick', 'grasp', 'hook']: elif action in ['pick', 'grasp', 'hook']:
substages = build_stage(action)(active_obj_id, passive_obj_id, active_elements, passive_elements, substages = build_stage(action)(active_obj_id, passive_obj_id, active_elements, passive_elements,
gripper2obj, extra_params=stage.get('extra_params', None)) gripper2obj, extra_params=stage.get('extra_params', None), active_obj=active_obj, passive_obj=passive_obj)
elif action in ['slide', 'shave', 'brush', 'wipe', 'pull', 'rotate', 'pull', 'move', elif action in ['slide', 'shave', 'brush', 'wipe', 'pull', 'rotate', 'move',
'reset']: # grasp + 物体自身运动 'reset', "pull_revolute", "twist"]: # grasp + 物体自身运动
passive_element = passive_elements[np.random.choice(len(passive_elements))] passive_element = passive_elements[np.random.choice(len(passive_elements))]
substages = build_stage(action)( substages = build_stage(action)(
active_obj_id=active_obj_id, active_obj_id=active_obj_id,
passive_obj_id=passive_obj_id, passive_obj_id=passive_obj_id,
passive_element=passive_element passive_element=passive_element,
active_obj=active_obj,
passive_obj=passive_obj,
target_pose=gripper2obj
) )
else: else:
passive_element = passive_elements[np.random.choice(len(passive_elements))] passive_element = passive_elements[np.random.choice(len(passive_elements))]
@@ -575,7 +599,7 @@ def generate_action_stages(objects, all_stages, robot):
ik_jacobian_score = ik_info["jacobian_score"][ik_success] ik_jacobian_score = ik_info["jacobian_score"][ik_success]
if len(target_gripper_poses_pass_ik) == 0: if len(target_gripper_poses_pass_ik) == 0:
print(action, ': No target_obj_pose can pass isaac curobo IK') Log.warning(f'{action}: No target_obj_pose can pass isaac curobo IK')
continue continue
target_joint_positions = [] target_joint_positions = []
@@ -617,12 +641,14 @@ def generate_action_stages(objects, all_stages, robot):
obj2part=obj2part, obj2part=obj2part,
vector_direction=passive_element['direction'], vector_direction=passive_element['direction'],
passive_element=passive_element, passive_element=passive_element,
extra_params=stage.get('extra_params', {}) extra_params=stage.get('extra_params', {}),
active_obj=active_obj,
passive_obj=passive_obj
) )
break break
if substages is None: if substages is None:
print(action, ': No target_obj_pose can pass IK') Log.warning(f'{action}:substage is None')
return [] return []
action_stages.append((action, substages)) action_stages.append((action, substages))

View File

@@ -49,9 +49,9 @@ class OmniObject:
"direction": np.array([-1, 0, 0.3]), "direction": np.array([-1, 0, 0.3]),
}, },
], ],
'click': { 'press': {
"part": "finger edge", "part": "finger edge",
"task": "click", "task": "press",
"xyz": np.array([0, 0, 0]), "xyz": np.array([0, 0, 0]),
"direction": np.array([0, 0, 1]), "direction": np.array([0, 0, 1]),
}, },
@@ -80,7 +80,6 @@ class OmniObject:
if "interaction" in obj_info: if "interaction" in obj_info:
obj_info = obj_info obj_info = obj_info
interaction_info = obj_info["interaction"] interaction_info = obj_info["interaction"]
part_joint_limits_info = obj_info.get("part_joint_limits", None)
else: else:
@@ -93,7 +92,6 @@ class OmniObject:
obj_info = json.load(open(obj_info_file)) obj_info = json.load(open(obj_info_file))
interaction_data = json.load(open(interaction_label_file)) interaction_data = json.load(open(interaction_label_file))
interaction_info = interaction_data['interaction'] interaction_info = interaction_data['interaction']
part_joint_limits_info = interaction_data.get("part_joint_limits", None)
obj = cls( obj = cls(
name=obj_info['object_id'], name=obj_info['object_id'],
@@ -104,10 +102,9 @@ class OmniObject:
if os.path.exists(mesh_file): if os.path.exists(mesh_file):
obj_info['mesh_file'] = mesh_file obj_info['mesh_file'] = mesh_file
obj.part_joint_limits = part_joint_limits_info
''' Load interaction labels ''' ''' Load interaction labels '''
obj.part_ids = []
for type in ['active', 'passive']: for type in ['active', 'passive']:
if type not in interaction_info: if type not in interaction_info:
continue continue
@@ -197,15 +194,14 @@ class OmniObject:
action_info[grasp_part] = grasp_data action_info[grasp_part] = grasp_data
interaction_info[type][action] = action_info interaction_info[type][action] = action_info
else: obj.is_articulated = obj_info.get("is_articulated", False)
for primitive in action_info: if obj.is_articulated:
for primitive_info in action_info[primitive]: obj.parts_info = obj_info["parts_info"]
if 'part_id' in primitive_info: obj.joints_info = obj_info["joints_info"]
obj.part_ids.append(primitive_info['part_id'])
obj.elements = interaction_info obj.elements = interaction_info
obj.info = obj_info obj.info = obj_info
# import ipdb;ipdb.set_trace() # import ipdb;ipdb.set_trace()
obj.is_articulated = True if part_joint_limits_info is not None else False
return obj return obj
def set_element(self, element): def set_element(self, element):

View File

@@ -133,17 +133,16 @@ class Agent(BaseAgent):
objects['fix_pose'].obj_pose[:3, :3] = rotation_matrix objects['fix_pose'].obj_pose[:3, :3] = rotation_matrix
continue continue
# TODO(unify part_name and obj_name) # TODO(unify part_name and obj_name)
if '/' in obj_id: obj = objects[obj_id]
if obj.is_articulated:
obj_name = obj_id.split('/')[0] obj_name = obj_id.split('/')[0]
part_name = obj_id.split('/')[1]
object_joint_state = self.robot.client.get_object_joint('/World/Objects/%s' % obj_name) object_joint_state = self.robot.client.get_object_joint('/World/Objects/%s' % obj_name)
for joint_name, joint_position, joint_velocity in zip(object_joint_state.joint_names, for joint_name, joint_position, joint_velocity in zip(object_joint_state.joint_names,
object_joint_state.joint_positions, object_joint_state.joint_positions,
object_joint_state.joint_velocities): object_joint_state.joint_velocities):
if joint_name[-1] == part_name[-1]: if joint_name == obj.joint_name:
objects[obj_id].joint_position = joint_position obj.joint_position = joint_position
objects[obj_id].joint_velocity = joint_velocity obj.joint_velocity = joint_velocity
objects[obj_id].obj_pose = self.robot.get_prim_world_pose('/World/Objects/%s' % obj_id) objects[obj_id].obj_pose = self.robot.get_prim_world_pose('/World/Objects/%s' % obj_id)
if hasattr(objects[obj_id], 'info') and 'simple_place' in objects[obj_id].info and objects[obj_id].info[ if hasattr(objects[obj_id], 'info') and 'simple_place' in objects[obj_id].info and objects[obj_id].info[
@@ -239,14 +238,15 @@ class Agent(BaseAgent):
camera_prim_list=camera_list, fps=fps, camera_prim_list=camera_list, fps=fps,
render_semantic=render_semantic) # TODO 录制判断 render_semantic=render_semantic) # TODO 录制判断
stage_id = -1
success = False success = False
substages = None substages = None
for _stages in split_stages: for _stages in split_stages:
stage_id = -1
extra_params = _stages[0].get('extra_params', {}) extra_params = _stages[0].get('extra_params', {})
active_id, passive_id = _stages[0]['active']['object_id'], _stages[0]['passive']['object_id'] active_id, passive_id = _stages[0]['active']['object_id'], _stages[0]['passive']['object_id']
arm = extra_params.get('arm', 'right') arm = extra_params.get('arm', 'right')
Log.info(f'Generating action stages [Executing task: {stage_id+1}/{len(split_stages)}]') Log.info(f'Generating action stages')
action_stages = generate_action_stages(objects, _stages, self.robot) action_stages = generate_action_stages(objects, _stages, self.robot)
if not len(action_stages): if not len(action_stages):
success = False success = False
@@ -255,12 +255,14 @@ class Agent(BaseAgent):
# Execution # Execution
success = True success = True
last_gripper_state = None
for action, substages in action_stages: for action, substages in action_stages:
stage_id += 1 stage_id += 1
Log.info(f'Start action stage: {action} [Executing task: {stage_id+1}/{len(action_stages)}]') Log.info(f'Start action stage: {action} [Executing task: {stage_id+1}/{len(action_stages)}]')
active_id, passive_id = _stages[stage_id]['active']['object_id'], _stages[stage_id]['passive'][ active_id, passive_id = _stages[stage_id]['active']['object_id'], _stages[stage_id]['passive'][
'object_id'] 'object_id']
if action in ['reset']: if action in ['reset']:
init_pose = self.robot.reset_pose[arm] init_pose = self.robot.reset_pose[arm]
curr_pose = self.robot.get_ee_pose(ee_type='gripper', id=arm) curr_pose = self.robot.get_ee_pose(ee_type='gripper', id=arm)
@@ -277,7 +279,6 @@ class Agent(BaseAgent):
self.robot.client.set_frame_state(action, substages.step_id, active_id, passive_id, self.robot.client.set_frame_state(action, substages.step_id, active_id, passive_id,
self.attached_obj_id is not None, arm=arm, self.attached_obj_id is not None, arm=arm,
target_pose=target_gripper_pose) target_pose=target_gripper_pose)
if target_gripper_pose is not None: if target_gripper_pose is not None:
self.robot.move_pose(target_gripper_pose, motion_type, arm=arm, block=True) self.robot.move_pose(target_gripper_pose, motion_type, arm=arm, block=True)
@@ -286,7 +287,9 @@ class Agent(BaseAgent):
self.robot.client.set_frame_state(action, substages.step_id, active_id, passive_id, self.robot.client.set_frame_state(action, substages.step_id, active_id, passive_id,
self.attached_obj_id is not None, set_gripper_open, self.attached_obj_id is not None, set_gripper_open,
set_gripper_close, arm=arm, target_pose=target_gripper_pose) set_gripper_close, arm=arm, target_pose=target_gripper_pose)
if last_gripper_state != gripper_action and gripper_action is not None:
self.robot.set_gripper_action(gripper_action, arm=arm) self.robot.set_gripper_action(gripper_action, arm=arm)
last_gripper_state = gripper_action
if gripper_action == 'open': if gripper_action == 'open':
time.sleep(1) time.sleep(1)
@@ -305,7 +308,7 @@ class Agent(BaseAgent):
if success == False: if success == False:
# import ipdb;ipdb.set_trace() # import ipdb;ipdb.set_trace()
self.attached_obj_id = None self.attached_obj_id = None
Log.error('Failed at sub-stage %d' % substages.step_id) Log.warning('Failed at sub-stage %d' % substages.step_id)
break break
# attach grasped object to gripper # TODO avoid articulated objects # attach grasped object to gripper # TODO avoid articulated objects

View File

@@ -48,9 +48,9 @@ class OmniObject:
"direction": np.array([-1,0,0.3]), "direction": np.array([-1,0,0.3]),
}, },
], ],
'click': { 'press': {
"part": "finger edge", "part": "finger edge",
"task": "click", "task": "press",
"xyz": np.array([0,0,0]), "xyz": np.array([0,0,0]),
"direction": np.array([0,0,1]), "direction": np.array([0,0,1]),
}, },