finshi press action
This commit is contained in:
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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])
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
34
data_gen_dependencies/action/press.py
Normal file
34
data_gen_dependencies/action/press.py
Normal 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'])
|
||||||
@@ -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
|
||||||
|
|||||||
110
data_gen_dependencies/action/pull_revolute.py
Normal file
110
data_gen_dependencies/action/pull_revolute.py
Normal 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
|
||||||
@@ -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'])
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
52
data_gen_dependencies/action/twist.py
Normal file
52
data_gen_dependencies/action/twist.py
Normal 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
|
||||||
@@ -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))
|
||||||
|
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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]),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user