예제 #1
0
def _convert_transform(pose):
    if pose is None:
        return tf.Transform3d()
    else:
        return tf.Transform3d(rot=tf.euler_angles_to_matrix(
            torch.tensor(pose[3:]), "ZYX"),
                              pos=pose[:3])
예제 #2
0
def _convert_transform(origin):
    if origin is None:
        return tf.Transform3d()
    else:
        return tf.Transform3d(rot=torch.tensor(tf2.quaternion_from_euler(
            *origin.rpy, "sxyz"),
                                               dtype=torch.float32),
                              pos=origin.xyz)
예제 #3
0
 def get_transform(self, theta):
     dtype = self.joint.axis.dtype
     d = self.joint.axis.device
     if self.joint.joint_type == 'revolute':
         t = tf.Transform3d(rot=tf.axis_angle_to_quaternion(theta * self.joint.axis), dtype=dtype, device=d)
     elif self.joint.joint_type == 'prismatic':
         t = tf.Transform3d(pos=theta * self.joint.axis, dtype=dtype, device=d)
     elif self.joint.joint_type == 'fixed':
         t = tf.Transform3d(default_batch_size=theta.shape[0], dtype=dtype, device=d)
     else:
         raise ValueError("Unsupported joint type %s." % self.joint.joint_type)
     return self.joint.offset.compose(t)
예제 #4
0
    def forward_kinematics(self, th, world=tf.Transform3d(), end_only=True):
        if world.dtype != self.dtype or world.device != self.device:
            world = world.to(dtype=self.dtype, device=self.device, copy=True)
        th, N = ensure_2d_tensor(th, self.dtype, self.device)

        cnt = 0
        link_transforms = {}
        trans = tf.Transform3d(matrix=world.get_matrix().repeat(N, 1, 1))
        for f in self._serial_frames:
            trans = trans.compose(f.get_transform(th[:, cnt].view(N, 1)))
            link_transforms[f.link.name] = trans.compose(f.link.offset)
            if f.joint.joint_type != "fixed":
                cnt += 1
        return link_transforms[self._serial_frames[-1].link.name] if end_only else link_transforms
예제 #5
0
def geoms_to_visuals(geom, base=tf.Transform3d()):
    visuals = []
    for g in geom:
        if g.type == 'capsule':
            param = (g.size[0], g.fromto)
        elif g.type == 'sphere':
            param = g.size[0]
        else:
            raise ValueError('Invalid geometry type %s.' % g.type)
        visuals.append(
            frame.Visual(offset=base.compose(
                tf.Transform3d(rot=g.quat, pos=g.pos)),
                         geom_type=g.type,
                         geom_param=param))
    return visuals
예제 #6
0
 def __init__(self,
              name=None,
              offset=tf.Transform3d(),
              joint_type='fixed',
              axis=(0.0, 0.0, 1.0),
              dtype=torch.float32,
              device="cpu"):
     self.name = name
     self.offset = offset
     if joint_type not in self.TYPES:
         raise RuntimeError(
             "joint specified as {} type not, but we only support {}".
             format(joint_type, self.TYPES))
     self.joint_type = joint_type
     if self.joint_type != 'fixed' and axis is None:
         self.axis = torch.tensor([0.0, 0.0, 1.0],
                                  dtype=dtype,
                                  device=device)
     else:
         if torch.is_tensor(axis):
             self.axis = axis.clone().detach().to(dtype=dtype,
                                                  device=device)
         else:
             self.axis = torch.tensor(axis, dtype=dtype, device=device)
     # normalize axis to have norm 1 (needed for correct representation scaling with theta)
     self.axis = self.axis / self.axis.norm()
예제 #7
0
 def __init__(self,
              offset=tf.Transform3d(),
              geom_type=None,
              geom_param=None):
     self.offset = offset
     self.geom_type = geom_type
     self.geom_param = geom_param
예제 #8
0
def calc_jacobian(serial_chain, th, tool=transforms.Transform3d()):
    """
    Return robot Jacobian J in base frame (N,6,DOF) where dot{x} = J dot{q}
    The first 3 rows relate the translational velocities and the
    last 3 rows relate the angular velocities.
    """
    if not torch.is_tensor(th):
        th = torch.tensor(th,
                          dtype=serial_chain.dtype,
                          device=serial_chain.device)
    if len(th.shape) <= 1:
        N = 1
        th = th.view(1, -1)
    else:
        N = th.shape[0]
    ndof = th.shape[1]
    if tool.dtype != serial_chain.dtype or tool.device != serial_chain.device:
        tool = tool.to(device=serial_chain.device,
                       copy=True,
                       dtype=serial_chain.dtype)

    j_fl = torch.zeros((N, 6, ndof),
                       dtype=serial_chain.dtype,
                       device=serial_chain.device)
    cur_transform = tool.get_matrix().repeat(N, 1, 1)

    cnt = 0
    for f in reversed(serial_chain._serial_frames):
        if f.joint.joint_type == "revolute":
            cnt += 1
            d = torch.stack([
                -cur_transform[:, 0, 0] * cur_transform[:, 1, 3] +
                cur_transform[:, 1, 0] * cur_transform[:, 0, 3],
                -cur_transform[:, 0, 1] * cur_transform[:, 1, 3] +
                cur_transform[:, 1, 1] * cur_transform[:, 0, 3],
                -cur_transform[:, 0, 2] * cur_transform[:, 1, 3] +
                cur_transform[:, 1, 2] * cur_transform[:, 0, 3]
            ]).transpose(0, 1)
            delta = cur_transform[:, 2, 0:3]
            j_fl[:, :, -cnt] = torch.cat((d, delta), dim=-1)
        elif f.joint.joint_type == "prismatic":
            cnt += 1
            j_fl[:, :3,
                 -cnt] = f.joint.axis.repeat(N, 1) @ cur_transform[:, :3, :3]
        cur_frame_transform = f.get_transform(th[:,
                                                 -cnt].view(N,
                                                            1)).get_matrix()
        cur_transform = cur_frame_transform @ cur_transform

    # currently j_fl is Jacobian in flange (end-effector) frame, convert to base/world frame
    pose = serial_chain.forward_kinematics(th).get_matrix()
    rotation = pose[:, :3, :3]
    j_tr = torch.zeros((N, 6, 6),
                       dtype=serial_chain.dtype,
                       device=serial_chain.device)
    j_tr[:, :3, :3] = rotation
    j_tr[:, 3:, 3:] = rotation
    j_w = j_tr @ j_fl
    return j_w
예제 #9
0
def add_composite_joint(root_frame, joints, base=tf.Transform3d()):
    if len(joints) > 0:
        root_frame.children = root_frame.children + (frame.Frame(
            link=frame.Link(name=root_frame.link.name + '_child'),
            joint=joint_to_joint(joints[0], base)), )
        ret, offset = add_composite_joint(root_frame.children[-1], joints[1:])
        return ret, root_frame.joint.offset.compose(offset)
    else:
        return root_frame, root_frame.joint.offset
예제 #10
0
    def _forward_kinematics(root, th_dict, world=tf.Transform3d()):
        link_transforms = {}

        th, N = ensure_2d_tensor(th_dict.get(root.joint.name, 0.0), world.dtype, world.device)

        trans = world.compose(root.get_transform(th.view(N, 1)))
        link_transforms[root.link.name] = trans.compose(root.link.offset)
        for child in root.children:
            link_transforms.update(Chain._forward_kinematics(child, th_dict, trans))
        return link_transforms
예제 #11
0
 def forward_kinematics(self, th, world=tf.Transform3d()):
     if not isinstance(th, dict):
         jn = self.get_joint_parameter_names()
         assert len(jn) == len(th)
         th_dict = dict((j, th[i]) for i, j in enumerate(jn))
     else:
         th_dict = th
     if world.dtype != self.dtype or world.device != self.device:
         world = world.to(dtype=self.dtype, device=self.device, copy=True)
     return self._forward_kinematics(self._root, th_dict, world)
예제 #12
0
def test_euler():
    euler_angles = torch.tensor([1, 0, 0.5])
    t = tf.Transform3d(rot=euler_angles)
    sxyz_matrix = torch.tensor([[0.87758256, -0.47942554, 0., 0., ],
                                [0.25903472, 0.47415988, -0.84147098, 0.],
                                [0.40342268, 0.73846026, 0.54030231, 0.],
                                [0., 0., 0., 1.]])
    # from tf.transformations import euler_matrix
    # print(euler_matrix(*euler_angles, "rxyz"))
    # print(t.get_matrix())
    assert torch.allclose(sxyz_matrix, t.get_matrix())
예제 #13
0
def test_transform_combined():
    R = tf.so3_exp_map(torch.randn((1, 3)))
    tr = torch.randn((1, 3))
    t = tf.Transform3d(rot=R, pos=tr)
    N = 10
    points = torch.randn((N, 3))
    normals = torch.randn((N, 3))
    points_out = t.transform_points(points)
    normals_out = t.transform_normals(normals)
    for i in range(N):
        assert torch.allclose(points_out[i], R @ points[i] + tr)
        assert torch.allclose(normals_out[i], R @ normals[i])
예제 #14
0
def test_rotate_axis_angle():
    t = tf.Transform3d().rotate_axis_angle(90.0, axis="Z")
    points = torch.tensor([[0.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 1.0, 1.0]]).view(
        1, 3, 3
    )
    normals = torch.tensor(
        [[1.0, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 0.0, 0.0]]
    ).view(1, 3, 3)
    points_out = t.transform_points(points)
    normals_out = t.transform_normals(normals)
    points_out_expected = torch.tensor(
        [[0.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 1.0]]
    ).view(1, 3, 3)
    normals_out_expected = torch.tensor(
        [[0.0, 1.0, 0.0], [0.0, 1.0, 0.0], [0.0, 1.0, 0.0]]
    ).view(1, 3, 3)
    assert torch.allclose(points_out, points_out_expected)
    assert torch.allclose(normals_out, normals_out_expected)
예제 #15
0
def test_rotate():
    R = tf.so3_exp_map(torch.randn((1, 3)))
    t = tf.Transform3d().rotate(R)
    points = torch.tensor([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.5, 0.5, 0.0]]).view(
        1, 3, 3
    )
    normals = torch.tensor(
        [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [1.0, 1.0, 0.0]]
    ).view(1, 3, 3)
    points_out = t.transform_points(points)
    normals_out = t.transform_normals(normals)
    points_out_expected = torch.bmm(points, R.transpose(-1, -2))
    normals_out_expected = torch.bmm(normals, R.transpose(-1, -2))
    assert torch.allclose(points_out, points_out_expected)
    assert torch.allclose(normals_out, normals_out_expected)
    for i in range(3):
        assert torch.allclose(points_out[0, i], R @ points[0, i])
        assert torch.allclose(normals_out[0, i], R @ normals[0, i])
예제 #16
0
def test_translations():
    t = tf.Translate(1, 2, 3)
    points = torch.tensor([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.5, 0.5, 0.0]]).view(
        1, 3, 3
    )
    points_out = t.transform_points(points)
    points_out_expected = torch.tensor(
        [[2.0, 2.0, 3.0], [1.0, 3.0, 3.0], [1.5, 2.5, 3.0]]
    ).view(1, 3, 3)
    assert torch.allclose(points_out, points_out_expected)

    N = 20
    points = torch.randn((N, N, 3))
    translation = torch.randn((N, 3))
    transforms = tf.Transform3d(pos=translation)
    translated_points = transforms.transform_points(points)
    assert torch.allclose(translated_points, translation.repeat(N, 1, 1).transpose(0, 1) + points)
    returned_points = transforms.inverse().transform_points(translated_points)
    assert torch.allclose(returned_points, points, atol=1e-6)
예제 #17
0
def _build_chain_recurse(root_frame, lmap, joints):
    children = []
    for j in joints:
        if j.parent == root_frame.link.name:
            child_frame = frame.Frame(j.child + "_frame")
            link_p = lmap[j.parent]
            link_c = lmap[j.child]
            t_p = _convert_transform(link_p.pose)
            t_c = _convert_transform(link_c.pose)
            child_frame.joint = frame.Joint(j.name,
                                            offset=t_p.inverse().compose(t_c),
                                            joint_type=JOINT_TYPE_MAP[j.type],
                                            axis=j.axis.xyz)
            child_frame.link = frame.Link(link_c.name,
                                          offset=tf.Transform3d(),
                                          visuals=_convert_visuals(
                                              link_c.visuals))
            child_frame.children = _build_chain_recurse(
                child_frame, lmap, joints)
            children.append(child_frame)
    return children
예제 #18
0
def build_chain_from_sdf(data):
    """
    Build a Chain object from SDF data.

    Parameters
    ----------
    data : str
        SDF string data.

    Returns
    -------
    chain.Chain
        Chain object created from SDF.
    """
    sdf = SDF.from_xml_string(data)
    robot = sdf.model
    lmap = robot.link_map
    joints = robot.joints
    n_joints = len(joints)
    has_root = [True for _ in range(len(joints))]
    for i in range(n_joints):
        for j in range(i + 1, n_joints):
            if joints[i].parent == joints[j].child:
                has_root[i] = False
            elif joints[j].parent == joints[i].child:
                has_root[j] = False
    for i in range(n_joints):
        if has_root[i]:
            root_link = lmap[joints[i].parent]
            break
    root_frame = frame.Frame(root_link.name + "_frame")
    root_frame.joint = frame.Joint(offset=_convert_transform(root_link.pose))
    root_frame.link = frame.Link(root_link.name, tf.Transform3d(),
                                 _convert_visuals(root_link.visuals))
    root_frame.children = _build_chain_recurse(root_frame, lmap, joints)
    return chain.Chain(root_frame)
예제 #19
0
def _convert_visuals(visuals):
    vlist = []
    for v in visuals:
        v_tf = _convert_transform(v.pose)
        if isinstance(v.geometry, Mesh):
            g_type = "mesh"
            g_param = v.geometry.filename
        elif isinstance(v.geometry, Cylinder):
            g_type = "cylinder"
            v_tf = v_tf.compose(
                tf.Transform3d(rot=tf.euler_angles_to_matrix(
                    torch.tensor([0.5 * math.pi, 0, 0]), "ZYX")))
            g_param = (v.geometry.radius, v.geometry.length)
        elif isinstance(v.geometry, Box):
            g_type = "box"
            g_param = v.geometry.size
        elif isinstance(v.geometry, Sphere):
            g_type = "sphere"
            g_param = v.geometry.radius
        else:
            g_type = None
            g_param = None
        vlist.append(frame.Visual(v_tf, g_type, g_param))
    return vlist
예제 #20
0
def body_to_link(body, base=tf.Transform3d()):
    return frame.Link(body.name,
                      offset=base.compose(
                          tf.Transform3d(rot=body.quat, pos=body.pos)))
예제 #21
0
def joint_to_joint(joint, base=tf.Transform3d()):
    return frame.Joint(joint.name,
                       offset=base.compose(tf.Transform3d(pos=joint.pos)),
                       joint_type=JOINT_TYPE_MAP[joint.type],
                       axis=joint.axis)
예제 #22
0
 def __init__(self, name=None, offset=tf.Transform3d(), visuals=()):
     self.name = name
     self.offset = offset
     self.visuals = visuals