Пример #1
0
    def test_twoTransformsFromOnePose(self):
        '''
        Test the creation of a transform and its inverse from the same pose.

        Given a single pose, two coordinate transforms with opposite polarity
        can be constructed; they should be the inverse of each other.
        '''
        mot = self.backend.randomMotion()
        pose = motions.PoseSpec(pose=pBA, motion=mot)

        A_ct_B = toCoordinateTransform(poseSpec=pose, polarity=R_ct_T)
        B_ct_A = toCoordinateTransform(poseSpec=pose, polarity=T_ct_R)

        self.assertTrue(A_ct_B.leftFrame == B_ct_A.rightFrame)
        self.assertTrue(A_ct_B.rightFrame == B_ct_A.leftFrame)

        # now check that the API is consistent, and we can use the
        # 'right_frame' argument instead of 'polarity', to achieve the same transforms
        A_ct_B_ = toCoordinateTransform(poseSpec=pose, right_frame=frB)
        B_ct_A_ = toCoordinateTransform(poseSpec=pose, right_frame=frA)
        self.assertTrue(A_ct_B == A_ct_B_)
        equals = (B_ct_A == B_ct_A_)
        self.assertTrue(equals)

        # Finally check that the matrix representation is consistent, one should
        # be the inverse of the other
        A_X_B = self.backend.asMatrix(A_ct_B)
        B_X_A = self.backend.asMatrix(B_ct_A)
        equals = self.backend.equal_matrix(
            self.backend.mult_matrix(A_X_B, B_X_A), self.backend.identity())
        self.assertTrue(equals)
Пример #2
0
def getDebugSample(numMixin, reprMixin):
    class Mixin(numMixin, reprMixin):
        pass

    obj = Mixin()
    mot = obj.randomMotion()
    pose = motions.PoseSpec(pose=pBA, motion=mot)
    A_ct_B = toCoordinateTransform(poseSpec=pose, polarity=R_ct_T)
    A_X_B = obj.asMatrix(A_ct_B)
    return mot, pose, A_ct_B, A_X_B
Пример #3
0
    def test_primitiveTransformPolarity(self):
        motion = self.backend.generator.randomMotion()
        pose = motions.PoseSpec(pose=pBA, motion=motion)
        tr1 = toCoordinateTransform(pose, primitives_polarity=R_ct_T)
        tr2 = toCoordinateTransform(pose, primitives_polarity=T_ct_R)
        M1 = self.backend.asMatrix(tr1)
        M2 = self.backend.asMatrix(tr2)

        equal = self.backend.equal_matrix(M1, M2)
        self.assertTrue(equal)
Пример #4
0
    def test_extrinsicIntrinsic(self):
        '''Test about extrinsic and intrinsic rotations

        Extrinsic rotations (ie about fixed axes) are equivalent to intrinsic
        rotations (about moving axes) in the opposite order'''

        rots = self.backend.randomRotations()
        extrinsic = MotionSequence(rots, MotionSequence.Mode.fixedFrame)
        intrinsic = MotionSequence(rots[::-1],
                                   MotionSequence.Mode.currentFrame)

        e_pose = motions.PoseSpec(pose=pBA, motion=extrinsic)
        i_pose = motions.PoseSpec(pose=pCB, motion=intrinsic)

        e_ct = toCoordinateTransform(e_pose)
        i_ct = toCoordinateTransform(i_pose)

        e_repr = self.backend.asMatrix(e_ct)
        i_repr = self.backend.asMatrix(i_ct)

        self.assertTrue(self.backend.equal_matrix(e_repr, i_repr))
Пример #5
0
    def test_poseInference(self):
        mot1 = self.backend.randomMotion()
        mot2 = self.backend.randomMotion()
        pose1 = motions.PoseSpec(pose=pBA, motion=mot1)
        pose2 = motions.PoseSpec(pose=pCB, motion=mot2)

        model = motions.PosesSpec(name='test', poses=[pose1, pose2])
        inspector = motions.ConnectedFramesInspector(model)
        self.assertTrue(inspector.hasRelativePose(frA, frC))

        posespec = inspector.getPoseSpec(targetFrame=frC, referenceFrame=frA)
        A_ct_B = toCoordinateTransform(pose1)
        B_ct_C = toCoordinateTransform(pose2)
        A_ct_C = toCoordinateTransform(posespec)  # to be tested

        A_X_B = self.backend.asMatrix(A_ct_B)
        B_X_C = self.backend.asMatrix(B_ct_C)
        A_X_C = self.backend.asMatrix(A_ct_C)

        self.assertTrue(
            self.backend.equal_matrix(self.backend.mult_matrix(A_X_B, B_X_C),
                                      A_X_C))
Пример #6
0
    def test_freeSymbols(self):
        '''Check the consistency of the data structures holding the free symbols of a matrix.
        '''
        mot1 = self.backend.randomMotion()
        pose1 = motions.PoseSpec(pose=pBA, motion=mot1)
        A_ct_B = toCoordinateTransform(pose1)

        A_X_B = self.backend.asMatrix(A_ct_B)

        setFromCTMetadata = set()
        setFromCTMetadata.update(
            [argument.symbol for argument in A_X_B.variables],
            [argument.symbol for argument in A_X_B.parameters],
            [argument.symbol for argument in A_X_B.constants])
        correct = (setFromCTMetadata == A_X_B.mx.free_symbols)
        if not correct:
            logger.error(
                "Symbols from the CT metadata: {0}\nSymbols from the Sympy matrix: {1}"
                .format(str(setFromCTMetadata), str(A_X_B.mx.free_symbols)))
        self.assertTrue(correct)
Пример #7
0
    def test_motionInversion(self):
        '''Test the inversion of a motion model

        The coordinate transform associated to the inverse of a motion M,
        should be the inverse of the transform associated to M.'''

        mot = self.backend.randomMotion()

        pose = motions.PoseSpec(pose=pBA, motion=mot)
        ipose = motions.inversePoseSpec(pose)

        A_ct_B = toCoordinateTransform(pose)
        B_ct_A = toCoordinateTransform(ipose)

        A_X_B = self.backend.asMatrix(A_ct_B)
        B_X_A = self.backend.asMatrix(B_ct_A)

        equal = self.backend.equal_matrix(
            self.backend.mult_matrix(A_X_B, B_X_A), self.backend.identity())
        self.assertTrue(equal)
Пример #8
0
    def test_duality(self):
        '''Check the relation between trasforms for spatial motion/force vectors.

        The transpose of a transform for spatial motion vectors is equal to the
        trasform for force vectors in the opposite polarity'''
        mot = self.backend.randomMotion()
        pose = motions.PoseSpec(pose=pBA, motion=mot)
        A_ct_B = toCoordinateTransform(poseSpec=pose,
                                       polarity=R_ct_T)  # CT from B to A
        B_ct_A = toCoordinateTransform(poseSpec=pose,
                                       polarity=T_ct_R)  # CT from A to B

        A_SM_B = self.backend.asMotionTransform(A_ct_B)
        B_SF_A = self.backend.asForceTransform(B_ct_A)
        good = self.backend.equal_matrix(self.backend.transpose(A_SM_B),
                                         B_SF_A)
        if not good:
            logger.error("\n" + self.backend.prettyStr(A_SM_B))
            logger.error("\n" + self.backend.prettyStr(B_SF_A))

        self.assertTrue(good)
Пример #9
0
    def __init__(self, connectModel, framesModel, posesModel, jointAxes=None):
        '''
        Construct the geometry model of a mechanism by composing the arguments.

        Parameters:

        - `connectModel` the connectivity model of the mechanism, with ordering
        - `framesModel` the set of the Cartesian frames attached to the mechanism
        - `posesModel` the constant, relative poses between the frames
        - `jointAxes` the versors of the joint axes, in joint frame coordinates

        The third argument is the actual geometric data; this constructor makes
        sure that the three arguments are consistent and therefore can be
        composed as a whole.

        In fact, the poses model stored in this instance is not the given
        `posesModel`. The input poses are always replaced by poses pointing to
        objects of `framesModel`. This is because the frames in the given
        `posesModel` might be simple placeholders. The name of the frame is used
        to establish the correspondence between a placeholder frame and a
        robot-attached frame.

        The `jointAxes` argument defaults to `None`. In that case it is assumed
        that the axis of any joint is the Z axis of its frame. Otherwise, the
        argument should be a dictionary indexed by joint name, with values being
        3-value tuples. Any tuple must represent the 3D joint axis versor, using
        coordinates in the joint frame.
        '''

        if not isinstance(connectModel, ordering.Robot):
            raise RuntimeError("An ordered robot model is required")
        rname = connectModel.name
        if framesModel.robot.name != rname:
            raise RuntimeError(
                "Robot name mismatch in the connectivity and frames model ('{0}' vs '{1})"
                .format(rname, framesModel.robot.name))

        self.byPose = {}
        for poseSpec in posesModel.poses:
            ignore = False
            pose = poseSpec.pose

            warnmsg = '''Frame '{0}' not found on the given frames-model '{1}', ignoring'''
            if pose.target.name not in framesModel.framesByName:
                logger.warning(warnmsg.format(pose.target.name, rname))
                ignore = True
            if pose.reference.name not in framesModel.framesByName:
                logger.warning(warnmsg.format(pose.reference.name, rname))
                ignore = True

            if not ignore:
                tgtF = framesModel.framesByName[pose.target.name]
                refF = framesModel.framesByName[pose.reference.name]
                path = framesModel.path(tgtF, refF)
                for i in range(len(path) - 1):
                    kind = framesModel.kind(path[i], path[i + 1])
                    if kind == frames.FrameRelationKind.acrossJoint:
                        warnmsg = '''Found non-constant pose in the geometry model
                        ('{0}' with respect to '{1}')'''.format(
                            tgtF.name, refF.name)
                        logger.warning(warnmsg)
                # Rebuild the Pose instance with the frames from the frames
                # model, which are attached to links. The pose instance from the
                # motions model (posesModel) might only refer to named frames
                realpose = Pose(target=tgtF, reference=refF)
                realposespec = motions.PoseSpec(pose=realpose,
                                                motion=poseSpec.motion)
                self.byPose[realpose] = realposespec
                #print( realpose )
                #print( poseSpec.motion.steps, "\n\n")

        # We iterate over joints and fetch the predecessor, as the joint_wrt_predecessor
        # is a constant pose also for loop joints.
        self.byJoint = {}
        for joint in connectModel.joints.values():
            predFrame = framesModel.linkFrames[connectModel.predecessor(joint)]
            jointFrame = framesModel.jointFrames[joint]
            pose = Pose(target=jointFrame, reference=predFrame)
            if pose not in self.byPose:
                logger.warning(
                    "The geometry model does not seem to have information about the pose of '{0}' wrt '{1}'"
                    .format(jointFrame.name, predFrame.name))
            else:
                self.byJoint[joint] = self.byPose[pose]

        self.ordering = connectModel
        self.frames = framesModel
        self.poses = motions.PosesSpec(posesModel.name,
                                       list(self.byPose.values()))
        # The last line creates a new PosesSpec model, to make sure we store the
        # model whose poses reference robot attached frames. As said before, the
        # PosesSpec model given to the constructor might have poses that refer
        # to the un-attached frames.

        if jointAxes == None:
            jointAxes = {}
            for joint in connectModel.joints.values():
                jointAxes[joint.name] = (0.0, 0.0, 1.0)  # default is Z axis
        else:
            if jointAxes.keys() != connectModel.joints.keys():
                logger.warning(
                    "The names in the joint-axes dictionary do not " +
                    "match the names in the connectivity model")
        self.axes = jointAxes
Пример #10
0
import kgprim.core as primitives
import kgprim.motions as mot
import kgprim.ct.frommotions as mot2ct
import kgprim.ct.repr.mxrepr as mxrepr

# make a motion sequence, with two steps
rx  = mot.MotionStep(mot.MotionStep.Kind.Rotation,    mot.Axis.X, 0.5)
ty  = mot.MotionStep(mot.MotionStep.Kind.Translation, mot.Axis.Y, 1.1)
seq = mot.MotionSequence([rx, ty], mot.MotionSequence.Mode.currentFrame)

# make a dummy pose
fR   = primitives.Frame('R')
fT   = primitives.Frame('T')
pose = primitives.Pose(reference=fR, target=fT)

# augment the pose with the motion spec; this object models the fact that to
# go from 'R' to 'T' one has to take the motion steps defined above
poseSpec = mot.PoseSpec(pose, seq)

# convert it to a coordinate transform model; by default, this is the transform
# from 'T' coordinates to 'R' coordinates, i.e. R_X_T
ct = mot2ct.toCoordinateTransform(poseSpec)

# use the functors in the matrix-representation module to get actual matrices
H = mxrepr.hCoordinatesNumeric( ct )
R = mxrepr.rotationMatrixNumeric( ct )

print(H)
print(R)