Пример #1
0
 def bases_to_Quat(xBasis, yBasis, zBasis):
     """ For new bases expressed in the old, find the quaternion that rotates the old onto the new """
     # FIXME , THIS IS WRONG , COMPARE TO 'principal_rot_Quat' !! FIXME , THIS IS WRONG , COMPARE TO 'principal_rot_Quat' !!
     Q = [vec_unit(xBasis), vec_unit(yBasis), vec_unit(zBasis)]
     [[Qxx, Qxy, Qxz], [Qyx, Qyy, Qyz], [Qzx, Qzy, Qzz]] = Q
     t = Qxx + Qyy + Qzz
     r = sqrt(1 + t)
     w = 0.5 * r
     x = copysign(0.5 * sqrt(1 + Qxx - Qyy - Qzz), (Qzy - Qyz))
     y = copysign(0.5 * sqrt(1 - Qxx + Qyy - Qzz), (Qxz - Qzx))
     z = copysign(0.5 * sqrt(1 - Qxx - Qyy + Qzz), (Qyx - Qxy))
     temp = Quaternion(w, x, y, z)
     temp.normalize()
     return temp
Пример #2
0
    def blend_in_steps(aPose, bPose, linStep=0.02, rotStep=0.087):
        """ Blend from 'aPose' to 'bPose' (inclusive) along a straight line and the shortest turn, not exceeding 'linStep' or 'rotStep' """
        poseDiff = Pose.diff_from_to(
            aPose, bPose)  # Obtain the difference between the two poses
        dist = vec_mag(poseDiff.position)
        k, rot = poseDiff.orientation.get_k_rot(
        )  # Get the axis-angle of the orientation difference
        if dist / linStep >= rot / rotStep:  # If more linear steps are needed than rotational steps
            distances = incr_max_step(0, dist, linStep)
            angles = np.linspace(0, rot, len(distances))
        else:  # else more rotational steps are needed than linear steps
            angles = incr_max_step(0, rot, rotStep)
            distances = np.linspace(0, dist, len(angles))

        direction = vec_unit(poseDiff.position)
        positions = [
            np.add(aPose.position, np.multiply(direction, disp))
            for disp in distances
        ]
        orientations = [
            Quaternion.compose_rots(aPose.orientation,
                                    Quaternion.k_rot_to_Quat(k, blendRot))
            for blendRot in angles
        ]

        rtnPoses = []
        for index in xrange(
                len(positions)):  # For each position-orientation pair
            rtnPoses.append(
                Pose(positions[index],
                     orientations[index]))  # construct a Pose and append
        return rtnPoses  # All done, return
Пример #3
0
 def __init__(self, pK, pTheta, pMinLimit=None, pMaxLimit=None):
     super(Rotation, self).set_k_rot(pK, pTheta)
     self.k = vec_unit(pK)
     self.theta = pTheta
     self.hasLimits = pMinLimit != None or pMaxLimit != None
     self.minLimit = pMinLimit
     self.maxLimit = pMaxLimit
Пример #4
0
 def shortest_btn_vecs(v1, v2):
     """ Return the Quaternion representing the shortest rotation from vector 'v1' to vector 'v2' """
     #        print "DEBUG , Got vectors:     " , v1 , v2
     #        print "DEBUG , Crossed vectors: " , np.cross( v1 , v2 )
     #        print "DEBUG , Crossed unit vec:" , vec_unit( np.cross( v1 , v2 ) )
     #        print "DEBUG , Angle between:   " , vec_angle_between( v1 , v2 )
     angle = vec_angle_between(v1, v2)
     if eq(angle, 0.0):
         return Quaternion.no_turn_quat()
     elif eq(angle, pi):
         # If we are making a pi turn, then just pick any axis perpendicular to the opposing vectors and make the turn
         # The axis that is picked will result in different poses
         return Quaternion.k_rot_to_Quat(vec_unit(np.cross(v1, [1, 0, 0])),
                                         angle)
     else:
         return Quaternion.k_rot_to_Quat(vec_unit(np.cross(v1, v2)), angle)
Пример #5
0
 def set_k_rot(self, k, rot):
     """ Set the quaternion components based on an axis-angle (radians) specification of rotation """
     k = vec_unit(k)
     self.sclr = cos(rot / 2)
     self._vctr = np.array([ k[0] * sin(rot/2) , \
                             k[1] * sin(rot/2) , \
                             k[2] * sin(rot/2) ])
Пример #6
0
def ray_intersects_triangle(rayOrigin, rayVector, CCWtriCoords):
    """ Möller–Trumbore intersection algorithm for whether a ray intersects a triangle in R3 , 'rayVector' can be any length 
        return: [ bool: Ray intersects triangle , R3: Line intersection point , float: signed distance from ray origin to intersection ] """
    # Note: If there is no line intersection , then the second and third elements will be populated with NaN
    vertex0 = CCWtriCoords[0]
    vertex1 = CCWtriCoords[1]
    vertex2 = CCWtriCoords[2]

    edge1 = np.subtract(vertex1, vertex0)
    edge2 = np.subtract(vertex2, vertex0)
    h = np.cross(rayVector, edge2)  # rayVector.crossProduct(edge2);
    a = np.dot(edge1, h)  # edge1.dotProduct(h);
    if (a > -EPSILON) and (a < EPSILON):
        return [False, vec_NaN(3), float('NaN')
                ]  # No intersection , Return False and in invalid vec
    f = 1.0 / a
    s = np.subtract(rayOrigin, vertex0)
    u = f * np.dot(s, h)  # u = f * (s.dotProduct(h));
    if (u < 0.0) or (u > 1.0):
        return [False, vec_NaN(3), float('NaN')
                ]  # No intersection , Return False and in invalid vec
    q = np.cross(s, edge1)  # s.crossProduct(edge1);
    v = f * np.dot(rayVector, q)  # f * rayVector.dotProduct(q);
    if (v < 0.0) or (u + v > 1.0):
        return [False, vec_NaN(3), float('NaN')
                ]  # No intersection , Return False and in invalid vec
    # At this stage we can compute t to find out where the intersection point is on the line.
    t = f * np.dot(edge2, q)  # f * edge2.dotProduct(q);
    outIntersectionPoint = np.add(rayOrigin, np.multiply(rayVector, t))
    intersectionMag = np.dot(np.subtract(outIntersectionPoint, rayOrigin),
                             vec_unit(rayVector))
    if t > EPSILON:  # ray intersection
        return [True, outIntersectionPoint, intersectionMag]
    else:  # This means that there is a line intersection but not a ray intersection.
        return [False, outIntersectionPoint, intersectionMag]
Пример #7
0
def circle_arc_3D(axis, center, radius, beginMeasureVec, theta, N):
    """ Return points on a circular arc about 'axis' at 'radius' , beginning at 'beginMeasureVec' and turning 'theta' through 'N' points """
    thetaList = np.linspace(0, theta, N)
    k = vec_unit(axis)
    rtnList = []
    # 1. Project the theta = 0 vector onto the circle plane
    measrVec = vec_unit(vec_proj_to_plane(beginMeasureVec, axis))
    # 2. For each theta
    for theta_i in thetaList:
        # 3. Create a rotation matrix for the rotation
        R = rot_matx_ang_axs(theta_i, k)
        # 4. Apply rotation to the measure vector && 5. Scale the vector to the radius && 6. Add to the center && 7. Append to the list
        rtnList.append(np.add(center, np.multiply(np.dot(R, measrVec),
                                                  radius)))
    # 8. Return
    return rtnList
Пример #8
0
 def principal_rot_Quat(basis1, basis2, basis3):
     """ For new 'bases' expressed in the old, find the quaternion that rotates the old onto the new """
     C = [vec_unit(basis1),
          vec_unit(basis2),
          vec_unit(basis3)
          ]  # Asssumed normalization enough times that I'll just do it
     inside = 0.5 * (C[0][0] + C[1][1] + C[2][2] - 1)
     # print "DEBUG , 0.5 * ( C[0][0] + C[1][1] + C[2][2] - 1 ):" , inside
     if abs(inside) > 1:
         # print "DEBUG , Applying correction!" , inside , "-->" ,
         inside = -decimal_part(inside)
         # print inside
     Phi = acos(inside)
     e1 = 0.5 * sin(Phi) * (C[1][2] - C[2][1])
     e2 = 0.5 * sin(Phi) * (C[2][0] - C[0][2])
     e3 = 0.5 * sin(Phi) * (C[0][1] - C[1][0])
     return Quaternion.k_rot_to_Quat([e1, e2, e3], Phi)
Пример #9
0
 def step_from_to(aPose, bPose, linStep, rotStep):
     """ Return a linear step and a rotational step from 'aPose' towards 'bPose' for use with Jacobian trajectories """
     poseDiff = Pose.diff_from_to(
         aPose, bPose)  # Obtain the difference between the two poses
     dist = vec_mag(poseDiff.position)
     vecStep = vec_unit(poseDiff.position
                        ) * linStep if dist > linStep else poseDiff.position
     vecStep = np.multiply(vec_unit(poseDiff.position),
                           linStep) if dist > linStep else poseDiff.position
     k, rot = poseDiff.orientation.get_k_rot(
     )  # Get the axis-angle of the orientation difference
     rotStep = rotStep if rotStep > rot else rot
     trnStep = np.multiply(k, rotStep)
     #      [ delta x    , delta y    , delta z    , k0 * d theta , k1 * d theta , k2 * d theta ]
     return [
         vecStep[0], vecStep[1], vecStep[2], trnStep[0], trnStep[1],
         trnStep[2]
     ]
Пример #10
0
 def k_rot_to_Quat(k, rot):
     """ Return a quaternion representing a rotation of 'rot' about 'k' 
     k :   3D vector that is the axis of rotation
     rot : rotation angle expressed in radians  """
     k = vec_unit(k)
     return Quaternion( cos(rot/2), \
                        k[0] * sin(rot/2), \
                        k[1] * sin(rot/2), \
                        k[2] * sin(rot/2) )
Пример #11
0
def principal_rotation_test():
    """ Test of 'Quaternion.principal_rot_Quat' """
    newBasisX = vec_unit([0.0, -1.0, 1.0])
    newBasisY = vec_unit([1.0, 0.0, 0.0])
    newBasisZ = vec_unit([0.0, 1.0, 1.0])
    if check_orthonormal(newBasisX, newBasisY, newBasisZ):
        print "New bases are orthonormal"
        principalQuat = Quaternion.principal_rot_Quat(newBasisX, newBasisY,
                                                      newBasisZ)
        testBasisX = principalQuat.apply_to([1, 0, 0])
        testBasisY = principalQuat.apply_to([0, 1, 0])
        testBasisZ = principalQuat.apply_to([0, 0, 1])
        print "New basis X", newBasisX, "and transformed basis X", testBasisX, "are equal:", vec_eq(
            newBasisX, testBasisX)
        print "New basis Y", newBasisY, "and transformed basis Y", testBasisY, "are equal:", vec_eq(
            newBasisY, testBasisY)
        print "New basis Z", newBasisZ, "and transformed basis Z", testBasisZ, "are equal:", vec_eq(
            newBasisZ, testBasisZ)
    else:
        print "New bases are not orthonormal"
Пример #12
0
 def single_step_from_to(aPose, bPose):
     """ Return the linear and rotational difference in the form [ delta x , delta y , delta z , k0 * d theta , k1 * d theta , k2 * d theta ] """
     poseDiff = Pose.diff_from_to(
         aPose, bPose)  # Obtain the difference between the two poses
     vecStep = vec_unit(poseDiff.position)
     k, rot = poseDiff.orientation.get_k_rot(
     )  # Get the axis-angle of the orientation difference
     trnStep = np.multiply(k, rot)
     #      [ delta x    , delta y    , delta z    , k0 * d theta , k1 * d theta , k2 * d theta ]
     return [
         vecStep[0], vecStep[1], vecStep[2], trnStep[0], trnStep[1],
         trnStep[2]
     ]
Пример #13
0
def vec_proj_to_plane(vec, planeNorm):
    """ Return a vector that is the projection of 'vec' onto a plane with the normal vector 'planeNorm', using numpy """
    # URL, projection of a vector onto a plane: http://www.euclideanspace.com/maths/geometry/elements/plane/lineOnPlane/
    # NOTE: This function assumes 'vec' and 'planeNorm' are expressed in the same bases
    if vec_eq(vec, [0, 0, 0]):
        return [0, 0, 0]
    else:
        projDir = vec_unit(np.cross(
            np.cross(planeNorm, vec),
            planeNorm))  # direction of the projected vector, normalize
        projMag = vec_proj(
            vec, projDir)  # magnitude of the vector in the projected direction
        return np.multiply(
            projDir, projMag
        )  # scale the unit direction vector to the calculated magnitude and return
Пример #14
0
 def set_k(self, pK):
     """ Update the vector and compute the quaternion 
     This function assumes that pK is a Vector """
     self.k = vec_unit(pK)
     self.set_k_rot(self.k, self.theta)  # compute the quaternion