def __init__(self,
              env,
              pos,
              quat,
              slacky_collision=True,
              halfsize=VIRTUAL_CUBOID_HALF_SIZE,
              ignore_collision=False,
              avoid_edge_faces=True,
              yawing_grasp=False,
              allow_partial_sol=False):
     self.object_pos = pos
     self.object_ori = quat
     self.ik = env.pinocchio_utils.inverse_kinematics
     self.id = env.platform.simfinger.finger_id
     self.tip_ids = env.platform.simfinger.pybullet_tip_link_indices
     self.link_ids = env.platform.simfinger.pybullet_link_indices
     self.T_cube_to_base = Transform(pos, quat)
     self.T_base_to_cube = self.T_cube_to_base.inverse()
     self.env = env
     self.ik_utils = IKUtils(env, yawing_grasp=yawing_grasp)
     self.slacky_collision = slacky_collision
     self._org_tips_init = np.array(
         self.env.platform.forward_kinematics(INIT_JOINT_CONF))
     self.halfsize = halfsize
     self.tip_solver = CuboidForceClosureTest(halfsize, CoulombFriction(MU))
     self.ignore_collision = ignore_collision
     self.avoid_edge_faces = avoid_edge_faces
     self.yawing_grasp = yawing_grasp
     self.allow_partial_sol = allow_partial_sol
def get_anticlockwise_two_finger_yawing_grasp(half_size, object_ori):
    R_base_to_cube = Transform(np.zeros(3), object_ori).inverse()
    z_cube = R_base_to_cube(np.array([0, 0, 1]))
    axis = np.argmax(np.abs(z_cube))
    above_point = []
    for i in range(3):
        if i == axis:
            above_point.append(half_size[i] + 0.02)
        else:
            above_point.append(0)

    side_centers = get_side_face_centers(half_size, object_ori)
    tip_to_center = 0.20
    ax1 = side_centers[1] - side_centers[0]
    ax2 = side_centers[3] - side_centers[2]
    g1 = np.array([
        side_centers[0] - tip_to_center * ax2,
        side_centers[1] + tip_to_center * ax2, above_point
    ])
    g2 = np.array([
        side_centers[0] + tip_to_center * ax2,
        side_centers[1] - tip_to_center * ax2, above_point
    ])
    # return [g1, g2]
    # return [g2]

    point = np.stack([
        #[0, half_size[1], 0],
        #[0, -half_size[1], 0],
        side_centers[0],
        side_centers[1],
        above_point
    ])

    return [point]
def _get_tip_path(cube_tip_positions, cube_path):
    def get_quat(euler):
        return p.getQuaternionFromEuler(euler)

    return [
        Transform(cube_pose[:3], get_quat(cube_pose[3:]))(cube_tip_positions)
        for cube_pose in cube_path
    ]
def sample_side_face(n, half_size, object_ori, shrink_region=[0.0, 0.6, 0.0]):
    R_base_to_cube = Transform(np.zeros(3), object_ori).inverse()
    z_cube = R_base_to_cube(np.array([0, 0, 1]))
    axis = np.argmax(np.abs(z_cube))
    sample_ax = np.array([i for i in range(3) if i != axis])
    points = np.stack([
        sample(np.random.choice(sample_ax), np.random.choice([-1, 1]),
               half_size, shrink_region) for _ in range(n)
    ])
    return points
def get_side_face_centers(half_size, object_ori):
    R_base_to_cube = Transform(np.zeros(3), object_ori).inverse()
    z_cube = R_base_to_cube(np.array([0, 0, 1]))
    axis = np.argmax(np.abs(z_cube))
    points = []
    for ax in range(3):
        if ax != axis:
            points.append(sample(ax, 1, half_size, np.zeros(3)))
            points.append(sample(ax, -1, half_size, np.zeros(3)))
    return np.array(points)
    def add_tip_adjustments(self, obs, num_steps=50):
        print("Appending to path....")
        # tip_pos = self.path.tip_path[-1]
        dir = 0.5 * (obs['goal_object_position'] - obs['object_position'])
        cube_pos = self.cube_sequence[-1][:3]
        cube_ori = p.getQuaternionFromEuler(self.cube_sequence[-1][3:])

        grasp = self.path.grasp
        if self.adjust_tip_ori:
            yaxis = np.array([0, 1, 0])
            goal_obj_yaxis = Rotation.from_quat(
                obs['goal_object_orientation']).apply(yaxis)
            obj_yaxis = Rotation.from_quat(cube_ori).apply(yaxis)
            diff_quat = get_rotation_between_vecs(obj_yaxis, goal_obj_yaxis)
            resolution = np.arange(0, 1, 1.0 / num_steps)
            interp_quat = slerp(np.array([0, 0, 0, 1]), diff_quat, resolution)

        warning_counter = 0
        warning_tips = []
        for i in range(num_steps):
            translation = cube_pos + i / num_steps * dir
            if self.adjust_tip_ori:
                rotation = (Rotation.from_quat(interp_quat[i]) *
                            Rotation.from_quat(cube_ori)).as_quat()
            else:
                rotation = cube_ori
            goal_tip_pos = Transform(translation, rotation)(grasp.cube_tip_pos)
            q = obs['robot_position']

            for j, tip in enumerate(goal_tip_pos):
                q = self.env.pinocchio_utils.inverse_kinematics(j, tip, q)
                if q is None:
                    q = self.joint_sequence[-1]
                    # print(f'[tip adjustments] warning: IK solution is not found for tip {j}. Using the last joint conf')
                    warning_counter += 1
                    if j not in warning_tips:
                        warning_tips.append(j)
                    break
            if q is None:
                print(
                    '[tip adjustments] warning: IK solution is not found for all tip positions.'
                )
                print(
                    f'[tip adjustments] aborting tip adjustments (loop {i} / {num_steps})'
                )
                break
            target_cube_pose = np.concatenate(
                [translation, p.getEulerFromQuaternion(rotation)])
            self.cube_sequence.append(target_cube_pose)
            self.joint_sequence.append(q)
            self.path.tip_path.append(goal_tip_pos)
        if warning_counter > 0:
            print(
                f'[tip adjustments] warning: IK solution is not found for {warning_counter} / {num_steps} times on tips {warning_tips}.'
            )
Example #7
0
 def _get_cone_corners(self):
     # approximate cone with an inscribed square
     contact_normal = np.array([0, 0, 1])
     fac = self.mu * np.sqrt(2) / 2
     corners = []
     transforms = []
     for i in [-1, +1]:
         for j in [-1, +1]:
             corner = np.array([i * fac, j * fac, 1])
             corner /= np.linalg.norm(corner)
             q = get_rotation_between_vecs(contact_normal, corner)
             corners.append(corner)
             transforms.append(Transform(pos=np.zeros(3), ori=q))
     return corners, transforms
def get_tiny_faces_heuristic_grasps(half_size, object_ori):
    R_base_to_cube = Transform(np.zeros(3), object_ori).inverse()
    z_cube = R_base_to_cube(np.array([0, 0, 1]))
    axis = np.argmax(np.abs(z_cube))
    above_point = []
    for i in range(3):
        if i == axis:
            above_point.append(half_size[i] + 0.02)
        else:
            above_point.append(0)

    point = np.stack([[0, half_size[1], 0], [0, -half_size[1], 0],
                      above_point])
    return [point]
Example #9
0
    def object_grasped(self, grasp):
        T_cube_to_base = Transform(self.obs['object_position'],
                                   self.obs['object_orientation'])
        target_tip_pos = T_cube_to_base(grasp.cube_tip_pos)
        center_of_tips = np.mean(target_tip_pos, axis=0)
        dist = np.linalg.norm(target_tip_pos - self.obs['robot_tip_positions'])
        center_dist = np.linalg.norm(center_of_tips - np.mean(self.obs['robot_tip_positions'], axis=0))
        object_is_grasped = center_dist < 0.07 and dist < 0.10
        if object_is_grasped:
            self.grasp_check_failed_count = 0
        else:
            self.grasp_check_failed_count += 1
            print('incremented grasp_check_failed_count')
            print(f'center_dist: {center_dist:.4f}\tdist: {dist:.4f}')

        return self.grasp_check_failed_count < 5
class Grasp(object):
    def __init__(self, cube_tip_pos, base_tip_pos, q, cube_pos, cube_quat,
                 T_cube_to_base, T_base_to_cube, valid_tips):
        self.cube_tip_pos = cube_tip_pos
        self.base_tip_pos = base_tip_pos
        self.q = q
        self.pos = cube_pos
        self.quat = cube_quat
        self.T_cube_to_base = T_cube_to_base
        self.T_base_to_cube = T_base_to_cube
        self.valid_tips = valid_tips

    def update(self, cube_pos, cube_quat):
        self.pos = cube_pos
        self.quat = cube_quat
        self.T_cube_to_base = Transform(self.pos, self.quat)
        self.T_base_to_cube = self.T_cube_to_base.inverse()
        self.base_tip_pos = self.T_cube_to_base(self.cube_tip_pos)
def get_long_side_face_centers(half_size, object_ori):
    # check if z-axis (cube-frame) is in parralel with z-axis in base-frame
    R_cube_to_base = Transform(np.zeros(3), object_ori)
    base_z = R_cube_to_base(np.array([0, 0, 1]))

    if np.argmax(np.abs(base_z)) == 2:
        # z-axis (cube-frame) is in parallel with z-axis in base-frame
        # --> sample from x-axis face
        axis = 0
    else:
        # z-axis (cube-frame) is in parallel with the floor
        # --> sample from z-axis face
        axis = 2
    points = [sample(axis, sign, half_size, np.zeros(3)) for sign in [-1, 1]]
    vertical_points = [
        sample(1, sign, half_size, np.zeros(3)) for sign in [-1, 1]
    ]  # TEMP
    return np.array(points), np.array(vertical_points)
Example #12
0
    def get_partial_grasp(self, execute=True, avg_pose=True):
        """
        sample a 'partial' grasp for object centering
        NOTE: Only use it for centering the object.
        """
        if avg_pose:
            obj_pos, obj_ori, self.obs, self.done = estimate_object_pose(
                self.env, self.obs, steps=AVG_POSE_STEPS
            )
        else:
            obj_pos = self.obs['object_position']
            obj_ori = self.obs['object_orientation']

        done = False
        while not done:
            grasp = grasping.sample_partial_grasp(self.env, obj_pos, obj_ori)
            if len(grasp.valid_tips) == 1:
                # NOTE: if only one of the tips is valid, check if
                # a. the tip is far from origin than object
                # b. angle between tip-to-origin vector and object's y-axis > 30 degree
                dist = np.linalg.norm(grasp.base_tip_pos[:, :2], axis=1)
                tip_id = np.argmax(dist)
                origin_to_tip = grasp.base_tip_pos[tip_id, :2]
                origin_to_tip /= np.linalg.norm(origin_to_tip)
                cube_yaxis = Transform(np.array([0, 0, 0]), obj_ori)(np.array([0, 1, 0]))[:2]
                cube_yaxis /= np.linalg.norm(cube_yaxis)
                # cube_yaxis = Rotation.from_quat(obj_ori).apply(np.array([0, 1, 0]))  # Is this same?
                if dist[tip_id] > np.linalg.norm(obj_pos) and np.dot(origin_to_tip, cube_yaxis) < 1 / 2:
                    print('grasp.valid_tips', grasp.valid_tips)
                    done = True
            else:
                done = True

        if grasp is not None and execute:
            self.obs, self.done = grasping.execute_grasp_approach(
                self.env, self.obs, grasp
            )

        if grasp is not None:
            self.env.unwrapped.register_custom_log('target_object_pose', {'position': obj_pos, 'orientation': obj_ori})
            self.env.unwrapped.register_custom_log('target_tip_pos', grasp.T_cube_to_base(grasp.cube_tip_pos))
            self.env.unwrapped.save_custom_logs()
        return grasp
Example #13
0
    def contact_from_tip_position(self, pos):
        """
        Compute contact frame from tip positions in the cube
        center of mass frame.
        """
        outside = np.abs(pos) >= self.halfsize - 1e-5
        sign = np.sign(pos)
        contact = pos.copy()
        normal = np.zeros(3)

        if np.sum(outside) == 0:
            outside[:] = True
        dist = np.minimum(np.abs(pos - self.halfsize),
                          np.abs(pos + self.halfsize))
        axes = np.argsort(dist)
        ax = [ax for ax in axes if outside[ax]][0]
        contact[ax] = sign[ax] * self.halfsize[ax]
        normal[ax] = -sign[ax]
        q = get_rotation_between_vecs(np.array([0, 0, 1]), normal)
        return Transform(pos=contact, ori=q)
def sample_long_side_face(n,
                          half_size,
                          object_ori,
                          shrink_region=[0.0, 0.6, 0.0]):
    '''sample from long side faces.
    long side face == x-axis or z-axis in the cube frame
    '''
    # check if z-axis (cube-frame) is in parralel with z-axis in base-frame
    R_cube_to_base = Transform(np.zeros(3), object_ori)
    base_z = R_cube_to_base(np.array([0, 0, 1]))

    if np.argmax(np.abs(base_z)) == 2:
        # z-axis (cube-frame) is in parallel with z-axis in base-frame
        # --> sample from x-axis face
        axis = 0
    else:
        # z-axis (cube-frame) is in parallel with the floor
        # --> sample from z-axis face
        axis = 2
    points = np.stack([
        sample(axis, np.random.choice([-1, 1]), half_size, shrink_region)
        for _ in range(n)
    ])
    return points
Example #15
0
 def update_tip_force_markers(self, obs, tip_wrenches, force):
     R_cube_to_base = Transform(np.zeros(3), obs['object_orientation'])
     cube_force = R_cube_to_base(force)
     self._set_markers([w[:3] for w in tip_wrenches],
                       obs['robot_tip_positions'], cube_force,
                       obs['object_position'])
 def update(self, cube_pos, cube_quat):
     self.pos = cube_pos
     self.quat = cube_quat
     self.T_cube_to_base = Transform(self.pos, self.quat)
     self.T_base_to_cube = self.T_cube_to_base.inverse()
     self.base_tip_pos = self.T_cube_to_base(self.cube_tip_pos)
class GraspSampler(object):
    def __init__(self,
                 env,
                 pos,
                 quat,
                 slacky_collision=True,
                 halfsize=VIRTUAL_CUBOID_HALF_SIZE,
                 ignore_collision=False,
                 avoid_edge_faces=True,
                 yawing_grasp=False,
                 allow_partial_sol=False):
        self.object_pos = pos
        self.object_ori = quat
        self.ik = env.pinocchio_utils.inverse_kinematics
        self.id = env.platform.simfinger.finger_id
        self.tip_ids = env.platform.simfinger.pybullet_tip_link_indices
        self.link_ids = env.platform.simfinger.pybullet_link_indices
        self.T_cube_to_base = Transform(pos, quat)
        self.T_base_to_cube = self.T_cube_to_base.inverse()
        self.env = env
        self.ik_utils = IKUtils(env, yawing_grasp=yawing_grasp)
        self.slacky_collision = slacky_collision
        self._org_tips_init = np.array(
            self.env.platform.forward_kinematics(INIT_JOINT_CONF))
        self.halfsize = halfsize
        self.tip_solver = CuboidForceClosureTest(halfsize, CoulombFriction(MU))
        self.ignore_collision = ignore_collision
        self.avoid_edge_faces = avoid_edge_faces
        self.yawing_grasp = yawing_grasp
        self.allow_partial_sol = allow_partial_sol

    def _reject(self, points_base):
        if not self.tip_solver.force_closure_test(self.T_cube_to_base,
                                                  points_base):
            return True, None
        if self.ignore_collision:
            q = self.ik_utils._sample_ik(points_base)
        elif self.allow_partial_sol:
            q = self.ik_utils._sample_ik(points_base, allow_partial_sol=True)
        else:
            q = self.ik_utils._sample_no_collision_ik(
                points_base,
                slacky_collision=self.slacky_collision,
                diagnosis=False)
        if q is None:
            return True, None
        return False, q

    def assign_positions_to_fingers(self, tips):
        cost_to_inds = {}
        for v in itertools.permutations([0, 1, 2]):
            sorted_tips = tips[v, :]
            cost = np.linalg.norm(sorted_tips - self._org_tips_init)
            cost_to_inds[cost] = v

        inds_sorted_by_cost = [
            val
            for key, val in sorted(cost_to_inds.items(), key=lambda x: x[0])
        ]
        opt_inds = inds_sorted_by_cost[0]
        opt_tips = tips[opt_inds, :]

        # verbose output
        return opt_tips, opt_inds, inds_sorted_by_cost

    def get_feasible_grasps_from_tips(self, tips):
        _, _, permutations_by_cost = self.assign_positions_to_fingers(tips)
        for perm in permutations_by_cost:
            ordered_tips = tips[perm, :]
            should_reject, q = self._reject(ordered_tips)
            if not should_reject:
                # use INIT_JOINT_CONF for tip positions that were not solvable
                valid_tips = [0, 1, 2]
                if self.allow_partial_sol:
                    for i in range(3):
                        if q[i * 3] is None:
                            valid_tips.remove(i)
                            q[i * 3:(i + 1) *
                              3] = INIT_JOINT_CONF[i * 3:(i + 1) * 3]

                yield Grasp(self.T_base_to_cube(ordered_tips), ordered_tips, q,
                            self.object_pos, self.object_ori,
                            self.T_cube_to_base, self.T_base_to_cube,
                            valid_tips)

    def __call__(self, shrink_region=[0.0, 0.6, 0.0], max_retries=40):
        retry = 0
        print("sampling a random grasp...")
        with keep_state(self.env):
            while retry < max_retries:
                print('[GraspSampler] retry count:', retry)
                points = sample_long_side_face(3,
                                               self.halfsize,
                                               self.object_ori,
                                               shrink_region=shrink_region)
                tips = self.T_cube_to_base(points)
                for grasp in self.get_feasible_grasps_from_tips(tips):
                    return grasp
                retry += 1

        raise RuntimeError('No feasible grasp is found.')

    def get_heuristic_grasps(self):
        grasps = get_all_heuristic_grasps(
            self.halfsize,
            self.object_ori,
            avoid_edge_faces=self.avoid_edge_faces,
            yawing_grasp=self.yawing_grasp,
            is_level_1=self.env.info['difficulty'] == 1)
        ret = []
        with keep_state(self.env):
            for points in grasps:
                tips = self.T_cube_to_base(points)
                # NOTE: we sacrifice a bit of speed by not using "yield", however,
                # context manager doesn't work as we want if we use "yield".
                # performance drop shouldn't be significant (get_feasible_grasps_from_tips only iterates 6 grasps!).
                # for grasp in self.get_feasible_grasps_from_tips(tips):
                #     yield grasp
                ret += [
                    grasp for grasp in self.get_feasible_grasps_from_tips(tips)
                ]
            return ret