Exemple #1
0
 def drawParticles2d(self, V, frame_id='origin', name='particles', lname='yaw', c=['b'], lc=['r'], ll=0.05):
     LD = []
     if len(V) < 1:
         print 'drawParticles2d -- no data? skip'
         return
     d,N = V[0].shape
     l = len(V)
     for v in V:
         Dv = np.vstack((v[0:2,:], np.zeros((1,N)))).T
         LD.append(Dv)
     publish_cloud(name, LD, c=c, frame_id=frame_id)
     if d > 2:
         count = -1
         DV = np.zeros((d,l*N))
         DT = np.zeros((d,l*N))
         for v in V:
             tt = np.zeros((d,N))
             for i in range(0,N):
                 t = Pose.from_rigid_transform(0,RigidTransform(xyzw=Quaternion.from_rpy(0,0,v[2,i]).to_xyzw(), tvec=[v[0,i], v[1,i], 0]))
                 pert = Pose.from_rigid_transform(0,RigidTransform(tvec=[ll,0,0]))
                 tv = (t.oplus(pert)).tvec
                 tt[0:2,i] = tv[0:2]
             count +=1
             DT[0:d,(count*N):((count+1)*N)] = tt
             Dv = np.vstack((v[0:2,:], np.zeros((1,N))))
             DV[0:d,(count*N):((count+1)*N)] = Dv
         publish_line_segments(lname, DV.T, DT.T, c=lc[0], frame_id=frame_id)
Exemple #2
0
 def random(cls, t=1):
     q_wxyz = [rnd.random(), rnd.random(), rnd.random(), rnd.random()]
     qmag = np.sqrt(sum([x * x for x in q_wxyz]))
     q_wxyz = [x / qmag for x in q_wxyz]
     translation = [
         rnd.uniform(-t, t),
         rnd.uniform(-t, t),
         rnd.uniform(-t, t)
     ]
     return cls(Quaternion.from_wxyz(q_wxyz), translation)
Exemple #3
0
 def drawParticles2d(self,
                     V,
                     frame_id='origin',
                     name='particles',
                     lname='yaw',
                     c=['b'],
                     lc=['r'],
                     ll=0.05):
     LD = []
     if len(V) < 1:
         print 'drawParticles2d -- no data? skip'
         return
     d, N = V[0].shape
     l = len(V)
     for v in V:
         Dv = np.vstack((v[0:2, :], np.zeros((1, N)))).T
         LD.append(Dv)
     publish_cloud(name, LD, c=c, frame_id=frame_id)
     if d > 2:
         count = -1
         DV = np.zeros((d, l * N))
         DT = np.zeros((d, l * N))
         for v in V:
             tt = np.zeros((d, N))
             for i in range(0, N):
                 t = Pose.from_rigid_transform(
                     0,
                     RigidTransform(xyzw=Quaternion.from_rpy(
                         0, 0, v[2, i]).to_xyzw(),
                                    tvec=[v[0, i], v[1, i], 0]))
                 pert = Pose.from_rigid_transform(
                     0, RigidTransform(tvec=[ll, 0, 0]))
                 tv = (t.oplus(pert)).tvec
                 tt[0:2, i] = tv[0:2]
             count += 1
             DT[0:d, (count * N):((count + 1) * N)] = tt
             Dv = np.vstack((v[0:2, :], np.zeros((1, N))))
             DV[0:d, (count * N):((count + 1) * N)] = Dv
         publish_line_segments(lname,
                               DV.T,
                               DT.T,
                               c=lc[0],
                               frame_id=frame_id)
Exemple #4
0
 def from_matrix(cls, T):
     return cls(Quaternion.from_matrix(T), T[:3, 3])
Exemple #5
0
 def __init__(self, xyzw=[0., 0., 0., 1.], tvec=[0., 0., 0.]):
     """ Initialize a RigidTransform with Quaternion and 3D Position """
     self.real = Quaternion(xyzw)
     self.dual = (Quaternion(xyzw=[tvec[0], tvec[1], tvec[2], 0.]) *
                  self.real) * 0.5
Exemple #6
0
class DualQuaternion(object):
    """
    SE(3) rigid transform class that allows compounding of 6-DOF poses
    and provides common transformations that are commonly seen in geometric problems.
        
    """
    def __init__(self, xyzw=[0., 0., 0., 1.], tvec=[0., 0., 0.]):
        """ Initialize a RigidTransform with Quaternion and 3D Position """
        self.real = Quaternion(xyzw)
        self.dual = (Quaternion(xyzw=[tvec[0], tvec[1], tvec[2], 0.]) *
                     self.real) * 0.5

    def __repr__(self):
        return 'real: %s dual: %s' % \
            (np.array_str(self.real, precision=2, suppress_small=True),
             np.array_str(self.dual, precision=2, suppress_small=True))

    def __add__(self, other):
        return DualQuaternion.from_dq(self.real + other.real,
                                      self.dual + other.dual)

    def __mul__(self, other):
        """ 
        Left-multiply RigidTransform with another rigid transform
        
        Two variants: 
           RigidTransform: Identical to oplus operation
           ndarray: transform [N x 3] point set (X_2 = p_21 * X_1)

        """
        if isinstance(other, DualQuaternion):
            return DualQuaternion.from_dq(
                other.real * self.real,
                other.dual * self.real + other.real * self.dual)
        elif isinstance(other, float):
            return DualQuaternion.from_dq(self.real * other, self.dual * other)
        # elif isinstance(other, nd.array):
        #     X = np.hstack([other, np.ones((len(other),1))]).T
        #     return (np.dot(self.matrix, X).T)[:,:3]
        else:
            raise TypeError('__mul__ typeerror {:}'.format(type(other)))

    def __rmul__(self, other):
        raise NotImplementedError('Right multiply not implemented yet!')

    def normalize(self):
        """ Check validity of unit-quaternion norm """
        self.real.normalize()
        self.dual.noramlize()

    def dot(self, other):
        return self.real.dot(other.real)

    def inverse(self):
        """ Returns a new RigidTransform that corresponds to the inverse of this one """
        qinv = self.dual.inverse()
        return DualQuaternion.from_dq(qinv.q, qinv.rotate(-self.tvec))

    def conjugate(self):
        return DualQuaternion.from_dq(self.real.conjugate(),
                                      self.dual.conjugate())

    def to_matrix(self):
        """ Returns a 4x4 homogenous matrix of the form [R t; 0 1] """
        result = self.rotation.to_matrix()
        result[:3, 3] = self.translation
        return result

    def to_Rt(self):
        """ Returns rotation R, and translational vector t """
        T = self.to_matrix()
        return T[:3, :3].copy(), T[:3, 3].copy()

    def to_wxyz(self):
        return self.rotation.to_wxyz()

    def to_xyzw(self):
        return self.rotation.to_xyzw()

    @classmethod
    def from_dq(cls, r, d):
        if not isinstance(r, DualQuaternion):
            raise TypeError('r is not DualQuaternion')
        if not not isinstance(d, DualQuaternion):
            raise TypeError('d is not DualQuaternion')

        a = cls()
        a.real = r
        a.dual = d
        return a

    @classmethod
    def from_Rt(cls, R, t):
        T = np.eye(4)
        T[:3, :3] = R.copy()
        T[:3, 3] = t.copy()
        return cls.from_matrix(T)

    @classmethod
    def from_matrix(cls, T):
        return cls(Quaternion.from_matrix(T), T[:3, 3])

    @property
    def rotation(self):
        return self.real

    @property
    def translation(self):
        t = self.dual.q * self.real.conjugate()
        return np.array([t.x, t.y, t.z]) * 2.0

    @classmethod
    def identity(cls):
        return cls()
Exemple #7
0
 def from_matrix(cls, T):
     sR_t = np.eye(4)
     sR_t[:3, :3] = T[:3, :3] / T[3, 3]
     return cls(Quaternion.from_matrix(sR_t), T[:3, 3], scale=1.0 / T[3, 3])
Exemple #8
0
 def from_angle_axis(cls, angle, axis, tvec):
     return cls(Quaternion.from_angle_axis(angle, axis), tvec)
Exemple #9
0
 def from_Rt(cls, R, t):
     T = np.eye(4)
     T[:3, :3] = R.copy()
     return cls(Quaternion.from_matrix(T), t)
Exemple #10
0
 def from_rpyxyz(cls, roll, pitch, yaw, x, y, z, axes='rxyz'):
     q = Quaternion.from_rpy(roll, pitch, yaw, axes=axes)
     return cls(q, (x, y, z))
Exemple #11
0
 def __init__(self, xyzw=[0., 0., 0., 1.], tvec=[0., 0., 0.]):
     """ Initialize a RigidTransform with Quaternion and 3D Position """
     self.quat = Quaternion(xyzw)
     self.tvec = np.float32(tvec)
Exemple #12
0
class RigidTransform(object):
    """
    SE(3) rigid transform class that allows compounding of 6-DOF poses
    and provides common transformations that are commonly seen in geometric problems.
    
    quat: Quaternion/Rotation (xyzw)
    tvec: Translation (xyz)
    """
    def __init__(self, xyzw=[0., 0., 0., 1.], tvec=[0., 0., 0.]):
        """ Initialize a RigidTransform with Quaternion and 3D Position """
        self.quat = Quaternion(xyzw)
        self.tvec = np.float32(tvec)

    def __repr__(self):
        return 'rpy (rxyz): %s tvec: %s' % \
            (np.array_str(self.quat.to_rpy(axes='rxyz'),
                          precision=2, suppress_small=True),
             np.array_str(self.tvec, precision=2, suppress_small=True))

    def __mul__(self, other):
        """ 
        Left-multiply RigidTransform with another rigid transform
   
        Two variants: 
           RigidTransform: Identical to oplus operation
              - self * other = self.oplus(other)
        
           ndarray: transform [N x 3] point set (X_2 = p_21 * X_1)
        """
        if isinstance(other, RigidTransform):
            return self.oplus(other)
        else:
            X = np.hstack([other, np.ones((len(other), 1))]).T
            return (np.dot(self.matrix, X).T)[:, :3]

    def __rmul__(self, other):
        raise NotImplementedError('Right multiply not implemented yet!')

    def copy(self):
        return RigidTransform(self.quat.copy(), self.tvec.copy())

    def inverse(self):
        """
        Returns a new RigidTransform that corresponds to the
        inverse of this one 
        """
        qinv = self.quat.inverse()
        return RigidTransform(qinv, qinv.rotate(-self.tvec))

    def oplus(self, other):
        if isinstance(other, RigidTransform):
            t = self.quat.rotate(other.tvec) + self.tvec
            r = self.quat * other.quat
            return RigidTransform(r, t)
        elif isinstance(other, list):
            return [self.oplus(o) for o in other]
        else:
            raise TypeError("Type inconsistent", type(other), other.__class__)

    def ominus(self, other):
        raise NotImplementedError()
        # if not isinstance(other, RigidTransform):
        #     raise TypeError("Type inconsistent")
        # oinv = other.inverse()
        # return oinv.oplus(self)

    def wrt(self, p_tr):
        """
        self: p_ro, desired: p_to
        o: other, r: reference, t: target
        """
        return self * p_tr

    def rotate_vec(self, v):
        if v.ndim == 2:
            return np.vstack([self.quat.rotate(v_) for v_ in v])
        else:
            assert (v.ndim == 1 or (v.ndim == 2 and v.shape[0] == 1))
            return self.quat.rotate(v)

    def interpolate(self, other, w):
        """
        LERP interpolation on rotation, and linear interpolation on position 
        Other approaches: 
        https://www.cvl.isy.liu.se/education/graduate/geometry-for-computer-vision-2014/geometry2014/lecture7.pdf
        """
        assert (w >= 0 and w <= 1.0)
        return self.from_Rt(
            self.rotation.interpolate(other.rotation, w).R,
            self.t + w * (other.t - self.t))

        # return self.from_Rt(self.R * expm3(w * logm(self.R.T * other.R)), self.t + w * (other.t - self.t))
        # return self.from_matrix(self.matrix * expm(w * logm((self.inverse() * other).matrix)))

    def to_matrix(self):
        """ Returns a 4x4 homogenous matrix of the form [R t; 0 1] """
        result = self.quat.to_matrix()
        result[:3, 3] = self.tvec
        return result

    def to_vector(self):
        """ Returns a 7-vector representation of 
        rigid transform [tx, ty, tz, qx, qy, qz, qw] 
        """
        return np.hstack([self.tvec, self.xyzw])

    def to_Rt(self):
        """ Returns rotation R, and translational vector t """
        T = self.to_matrix()
        return T[:3, :3].copy(), T[:3, 3].copy()

    def to_rpyxyz(self, axes='rxyz'):
        r, p, y = self.quat.to_rpy(axes=axes)
        return np.array((r, p, y, self.tvec[0], self.tvec[1], self.tvec[2]))

    @classmethod
    def from_rpyxyz(cls, roll, pitch, yaw, x, y, z, axes='rxyz'):
        q = Quaternion.from_rpy(roll, pitch, yaw, axes=axes)
        return cls(q, (x, y, z))

    @classmethod
    def from_Rt(cls, R, t):
        T = np.eye(4)
        T[:3, :3] = R.copy()
        return cls(Quaternion.from_matrix(T), t)

    @classmethod
    def from_matrix(cls, T):
        return cls(Quaternion.from_matrix(T), T[:3, 3])

    @classmethod
    def from_vector(cls, v):
        return cls(xyzw=v[3:], tvec=v[:3])

    @classmethod
    def from_triad(cls, pos, v1, v2):
        return RigidTransform.from_matrix(tf_compose(tf_construct(v1, v2),
                                                     pos))

    @classmethod
    def from_angle_axis(cls, angle, axis, tvec):
        return cls(Quaternion.from_angle_axis(angle, axis), tvec)

    @property
    def wxyz(self):
        return self.quat.wxyz

    @property
    def xyzw(self):
        return self.quat.xyzw

    @property
    def R(self):
        return self.quat.R

    @property
    def t(self):
        return self.tvec

    @property
    def orientation(self):
        return self.quat

    @property
    def rotation(self):
        return self.quat

    @property
    def rpyxyz(self):
        return self.to_rpyxyz()

    @property
    def translation(self):
        return self.tvec

    @classmethod
    def identity(cls):
        return cls()

    @classmethod
    def random(cls, t=1):
        q_wxyz = [rnd.random(), rnd.random(), rnd.random(), rnd.random()]
        qmag = np.sqrt(sum([x * x for x in q_wxyz]))
        q_wxyz = [x / qmag for x in q_wxyz]
        translation = [
            rnd.uniform(-t, t),
            rnd.uniform(-t, t),
            rnd.uniform(-t, t)
        ]
        return cls(Quaternion.from_wxyz(q_wxyz), translation)

    @property
    def matrix(self):
        return self.to_matrix()

    @property
    def vector(self):
        return self.to_vector()

    def scaled(self, scale):
        " Returns Sim3 representation of rigid-body transformation with scale "
        return Sim3(xyzw=self.xyzw, tvec=self.tvec, scale=scale)
Exemple #13
0
class RigidTransform(object):
    """
    SE(3) rigid transform class that allows compounding of 6-DOF poses
    and provides common transformations that are commonly seen in geometric problems.
    
    quat: Quaternion/Rotation (xyzw)
    tvec: Translation (xyz)
    
    """
    def __init__(self, xyzw=[0.,0.,0.,1.], tvec=[0.,0.,0.]):
        """ Initialize a RigidTransform with Quaternion and 3D Position """
        self.quat = Quaternion(xyzw)
        self.tvec = np.array(tvec)

    def __repr__(self):
        return 'rpy (rxyz): %s tvec: %s' % \
            (np.array_str(self.quat.to_rpy(axes='rxyz'), precision=2, suppress_small=True), 
             np.array_str(self.tvec, precision=2, suppress_small=True))
        # return 'quat: %s, tvec: %s' % (self.quat, self.tvec)

    def __mul__(self, other):
        """ 
        Left-multiply RigidTransform with another rigid transform
        
        Two variants: 
           RigidTransform: Identical to oplus operation
           ndarray: transform [N x 3] point set (X_2 = p_21 * X_1)

        """
        if isinstance(other, RigidTransform):
            return self.oplus(other)
        else:          
            X = np.hstack([other, np.ones((len(other),1))]).T
            return (np.dot(self.matrix, X).T)[:,:3]

    def __rmul__(self, other): 
        raise NotImplementedError('Right multiply not implemented yet!')                    

    # Basic operations

    def inverse(self):
        """ Returns a new RigidTransform that corresponds to the inverse of this one """
        qinv = self.quat.inverse()
        return RigidTransform(qinv, qinv.rotate(-self.tvec))

    def oplus(self, other): 
        if isinstance(other, RigidTransform): 
            t = self.quat.rotate(other.tvec) + self.tvec
            r = self.quat * other.quat
            return RigidTransform(r, t)
        elif isinstance(other, list): 
            return map(lambda o: self.oplus(o), other)
        else: 
            raise TypeError("Type inconsistent", type(other), other.__class__)

    def wrt(self, p_tr): 
        """
        self: p_ro, desired: p_to
        o: other, r: reference, t: target
        """
        return self * p_tr

    def rotate_vec(self, v): 
        if v.ndim == 2: 
            return np.vstack(map(lambda v_: self.quat.rotate(v_), v))
        else: 
            assert(v.ndim == 1 or (v.ndim == 2 and v.shape[0] == 1))
            return self.quat.rotate(v)


    def interpolate(self, other, w): 
        """
        LERP interpolation on rotation, and linear interpolation on position 
        Other approaches: 
        https://www.cvl.isy.liu.se/education/graduate/geometry-for-computer-vision-2014/geometry2014/lecture7.pdf
        """
        assert(w >= 0 and w <= 1.0)
        return self.from_Rt(self.rotation.interpolate(other.rotation, w).R, self.t + w * (other.t - self.t))

        # return self.from_Rt(self.R * expm3(w * logm(self.R.T * other.R)), self.t + w * (other.t - self.t))
        # return self.from_matrix(self.matrix * expm(w * logm((self.inverse() * other).matrix)))

    # def interpolate(self, other_transform, this_weight):
    #     assert this_weight >= 0 and this_weight <= 1
    #     t = self.tvec * this_weight + other_transform.tvec * (1 - this_weight)
    #     r = self.quat.interpolate(other_transform.quat, this_weight)
    #     return RigidTransform(r, t)

    # def ominus(self, other): 
    #     if not isinstance(other, RigidTransform): 
    #         raise TypeError("Type inconsistent")
    #     oinv = other.inverse()
    #     return oinv.oplus(self)


    # (To) Conversions

    def to_matrix(self):
        """ Returns a 4x4 homogenous matrix of the form [R t; 0 1] """
        result = self.quat.to_matrix()
        result[:3, 3] = self.tvec
        return result

    def to_Rt(self):
        """ Returns rotation R, and translational vector t """
        T = self.to_matrix()
        return T[:3,:3].copy(), T[:3,3].copy()

    def to_rpyxyz(self, axes='rxyz'):
        r, p, y = self.quat.to_rpy(axes=axes)
        return np.array((r, p, y, self.tvec[0], self.tvec[1], self.tvec[2]))


    # (From) Conversions

    @classmethod
    def from_rpyxyz(cls, roll, pitch, yaw, x, y, z, axes='rxyz'):
        q = Quaternion.from_rpy(roll, pitch, yaw, axes=axes)
        return cls(q, (x, y, z))

    @classmethod
    def from_Rt(cls, R, t):
        T = np.eye(4)
        T[:3,:3] = R.copy();
        return cls(Quaternion.from_matrix(T), t)

    @classmethod
    def from_matrix(cls, T):
        return cls(Quaternion.from_matrix(T), T[:3,3])

    @classmethod
    def from_triad(cls, pos, v1, v2):
        # print v1, v2, type(v1)
        return RigidTransform.from_matrix(tf_compose(tf_construct(v1, v2), pos))

    @classmethod
    def from_angle_axis(cls, angle, axis, tvec): 
        return cls(Quaternion.from_angle_axis(angle, axis), tvec)

    # Properties
    @property
    def wxyz(self):
        return self.quat.wxyz

    @property
    def xyzw(self):
        return self.quat.xyzw

    @property
    def R(self): 
        return self.quat.R

    @property
    def t(self): 
        return self.tvec

    @property
    def orientation(self): 
        return self.quat

    @property
    def rotation(self): 
        return self.quat

    @property
    def translation(self):
        return self.tvec

    @classmethod
    def identity(cls):
        return cls()

    @property
    def matrix(self): 
        return self.to_matrix()
Exemple #14
0
 def make_random_transform(t=1):
     q_wxyz = [ random.random(), random.random(), random.random(), random.random() ]
     qmag = np.sqrt(sum([x*x for x in q_wxyz]))
     q_wxyz = [ x / qmag for x in q_wxyz ]
     translation = [ random.uniform(-t, t), random.uniform(-t, t), random.uniform(-t, t) ]
     return RigidTransform(Quaternion.from_wxyz(q_wxyz), translation)
Exemple #15
0
             np.array_str(self.quat.to_rpy(axes='rxyz'), precision=2), 
             np.array_str(self.tvec, precision=2))

if __name__ == "__main__":

    import random

    def make_random_transform(t=1):
        q_wxyz = [ random.random(), random.random(), random.random(), random.random() ]
        qmag = np.sqrt(sum([x*x for x in q_wxyz]))
        q_wxyz = [ x / qmag for x in q_wxyz ]
        translation = [ random.uniform(-t, t), random.uniform(-t, t), random.uniform(-t, t) ]
        return RigidTransform(Quaternion.from_wxyz(q_wxyz), translation)


    q = Quaternion.identity()
    t = [ 1, 2, 3 ]
    m = RigidTransform(q, t)
    print "m"
    print m.to_matrix()
    print "--------------------------"

    q2 = Quaternion.from_rpy(np.pi / 4, 0, 0)
    t2 = [ 0, 0, 0 ]
    m2 = RigidTransform(q2, t2)
    print "m2"
    print m2.to_matrix()

    print "--------------------------"
    m3 = m * m2
    print "m * m2"