Esempio n. 1
0
    def test_construction(self):
        # Valid
        RotateYpr(10, 20, 30)

        # Invalid
        with self.assertRaises(TypeError):
            RotateYpr(1, 2, "3")
Esempio n. 2
0
    def test_equality(self):
        # Same object
        self.assertEqualToItself(RotateYpr(10, 20, 30))

        # Equal objects
        self.assertEqual(RotateYpr(10, 20, 30), RotateYpr(10, 20, 30))  # Equal

        # Different objects
        self.assertNotEqual(RotateYpr(10, 20, 30),
                            RotateYpr(10, 20, 40))  # Different values
Esempio n. 3
0
    def test_rotate(self):
        # Canonical axis/angle
        self.assertEqual(rotate(axis = Vector(1, 2, 3), angle = 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # Vector
        self.assertEqual(rotate(axis =       [1, 2, 3], angle = 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # List

        # Canonical from/to
        self.assertEqual(rotate(frm = Vector(1, 2, 3), to = Vector(4, 5, 6)), RotateFromTo(Vector(1, 2, 3), Vector(4, 5, 6))) # Vectors
        self.assertEqual(rotate(frm =       [1, 2, 3], to =       [4, 5, 6]), RotateFromTo(Vector(1, 2, 3), Vector(4, 5, 6))) # Lists

        # Canonical XYZ
        self.assertEqual(rotate(xyz = [45, 0, 30]), RotateXyz(45, 0, 30))

        # Canonical yaw/pitch/roll
        self.assertEqual(rotate(ypr = [90, -20, 5]), RotateYpr(90, -20, 5))

        # Convenience axis/angle (implicit)
        self.assertEqual(rotate(Vector(1, 2, 3), 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # Vector
        self.assertEqual(rotate(      [1, 2, 3], 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # List

        # Convenience axis/angle (explicit)
        self.assertEqual(rotate(Vector(1, 2, 3), angle = 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # Vector
        self.assertEqual(rotate(      [1, 2, 3], angle = 45), RotateAxisAngle(Vector(1, 2, 3), 45)) # List

        # Convenience from/to (implicit)
        self.assertEqual(rotate(X        , Y        ), RotateFromTo(X, Y)) # Vectors
        self.assertEqual(rotate([1, 0, 0], [0, 1, 0]), RotateFromTo(X, Y)) # Lists

        # Convenience from/to (explicit)
        self.assertEqual(rotate(X        , to = Y        ), RotateFromTo(X, Y)) # Vectors
        self.assertEqual(rotate([1, 0, 0], to = [0, 1, 0]), RotateFromTo(X, Y)) # Lists
Esempio n. 4
0
 def test_str(self):
     self.assertStr(RotateYpr(0, 0, 0), "Yaw, pitch, and roll by 0°")
     self.assertStr(RotateYpr(1, 0, 0), "Yaw 1°")
     self.assertStr(RotateYpr(0, 2, 0), "Pitch 2°")
     self.assertStr(RotateYpr(0, 0, 3), "Roll 3°")
     self.assertStr(RotateYpr(1, 2, 0), "Yaw 1°, pitch 2°")
     self.assertStr(RotateYpr(1, 0, 3), "Yaw 1°, roll 3°")
     self.assertStr(RotateYpr(0, 2, 3), "Pitch 2°, roll 3°")
     self.assertStr(RotateYpr(1, 2, 3), "Yaw 1°, pitch 2°, roll 3°")
Esempio n. 5
0
 def test_rotate_shortcuts(self):
     self.assertEqual(shortcuts.yaw_left(1), RotateYpr(1, 0, 0))
     self.assertEqual(shortcuts.yaw_right(2), RotateYpr(-2, 0, 0))
     self.assertEqual(shortcuts.pitch_up(3), RotateYpr(0, 3, 0))
     self.assertEqual(shortcuts.pitch_down(4), RotateYpr(0, -4, 0))
     self.assertEqual(shortcuts.roll_right(5), RotateYpr(0, 0, 5))
     self.assertEqual(shortcuts.roll_left(6), RotateYpr(0, 0, -6))
Esempio n. 6
0
    def test_to_scad(self):
        self.ignore_scad_comments = True

        # Since OpenSCAD does not have YPR rotations, they have to translated to
        # corresponding XYZ rotations.

        # A zero YPR transform is a zero XYZ transform (not an empty ScadObject,
        # which would also be possible).
        self.assertEqual(
            RotateYpr(0, 0, 0).to_scad(None),
            ScadObject("rotate", [[0, 0, 0]], None, None))

        # A single-axis YPR rotation can be expressed as a single-axis YPR
        # rotation.
        # Yaw - Z axis
        self.assertEqual(
            RotateYpr(1, 0, 0).to_scad(None),
            ScadObject("rotate", [[0, 0, 1]], None, None))
        # Pitch - X axis
        self.assertEqual(
            RotateYpr(0, 2, 0).to_scad(None),
            ScadObject("rotate", [[2, 0, 0]], None, None))
        # Roll - Y axis
        self.assertEqual(
            RotateYpr(0, 0, 3).to_scad(None),
            ScadObject("rotate", [[0, 3, 0]], None, None))

        # A dual-axis YPR rotation must be expressed as a chain of two single-
        # axis XYZ rotations (except in the case of yaw and pitch, which can be
        # combined).
        self.assertEqual(
            RotateYpr(0, 2, 3).to_scad(None),
            ScadObject("rotate", [[2, 0, 0]], None,
                       [ScadObject("rotate", [[0, 3, 0]], None, None)]))
        self.assertEqual(
            RotateYpr(1, 0, 3).to_scad(None),
            ScadObject("rotate", [[0, 0, 1]], None,
                       [ScadObject("rotate", [[0, 3, 0]], None, None)]))
        self.assertEqual(
            RotateYpr(1, 2, 0).to_scad(None),
            ScadObject("rotate", [[2, 0, 1]], None, None))

        # A tripel-axis YPR rotation must be expressed as a chain of two
        # single-axis XYZ rotations (yaw and pitch can be combined).
        self.assertEqual(
            RotateYpr(1, 2, 3).to_scad(None),
            ScadObject("rotate", [[2, 0, 1]], None,
                       [ScadObject("rotate", [[0, 3, 0]], None, None)]))
Esempio n. 7
0
    def test_inequality(self):
        # Different-type transformations are not equal (even if the values are identical)
        transforms = [
            RotateAxisAngle(X, 0),
            RotateFromTo(X, X),
            RotateXyz(0, 0, 0),
            RotateYpr(0, 0, 0),
            ScaleAxisFactor(X, 1),
            ScaleUniform(1),
            ScaleAxes (1, 1, 1),
            Translate([0, 0, 0]),
        ]

        for t1 in transforms:
            for t2 in transforms:
                if t1 is not t2:
                    self.assertNotEqual(t1, t2)
Esempio n. 8
0
    def test_transform_shortcuts(self):
        a = Cuboid(11, 11, 11)

        self.assertEqual(a.up     (1), Transformed(Translate([ 0,  0,  1]), a))
        self.assertEqual(a.down   (2), Transformed(Translate([ 0,  0, -2]), a))
        self.assertEqual(a.left   (3), Transformed(Translate([-3,  0,  0]), a))
        self.assertEqual(a.right  (4), Transformed(Translate([ 4,  0,  0]), a))
        self.assertEqual(a.forward(5), Transformed(Translate([ 0,  5,  0]), a))
        self.assertEqual(a.back   (6), Transformed(Translate([ 0, -6,  0]), a))

        self.assertEqual(a.yaw_left  (1), Transformed(RotateYpr( 1,  0,  0), a))
        self.assertEqual(a.yaw_right (2), Transformed(RotateYpr(-2,  0,  0), a))
        self.assertEqual(a.pitch_up  (3), Transformed(RotateYpr( 0,  3,  0), a))
        self.assertEqual(a.pitch_down(4), Transformed(RotateYpr( 0, -4,  0), a))
        self.assertEqual(a.roll_right(5), Transformed(RotateYpr( 0,  0,  5), a))
        self.assertEqual(a.roll_left (6), Transformed(RotateYpr( 0,  0, -6), a))
Esempio n. 9
0
def roll_left(r):
    return RotateYpr(0, 0, -r)
Esempio n. 10
0
def roll_right(r):
    return RotateYpr(0, 0, r)
Esempio n. 11
0
def pitch_down(p):
    return RotateYpr(0, -p, 0)
Esempio n. 12
0
def pitch_up(p):
    return RotateYpr(0, p, 0)
Esempio n. 13
0
def yaw_right(y):
    return RotateYpr(-y, 0, 0)
Esempio n. 14
0
def yaw_left(y):
    return RotateYpr(y, 0, 0)
Esempio n. 15
0
def rotate(axis_or_frm = None, angle_or_to = None, axis = None, angle = None, frm = None, to = None, xyz = None, ypr = None, ignore_ambiguity = False):
    """Generate a rotation around an axis through the origin.

    Signatures (canonical forms):
      * rotate(axis = x, angle = 45)
      * rotate(frm = x, to = y)
      * rotate(xyz = [45, 0, 30])
      * rotate(ypr = [45, -30, 10])
    Signatures (convenience forms):
      * rotate(x, 45)
      * rotate(x, angle = 45)
      * rotate(x, y)
      * rotate(x, to = y)
    """

    # Canonical forms:
    #     axis_or_axmag_or_frm  angle_or_to  axis  angle  frm   to   xyz   ypr
    #                        -            -   vec    num    -    -     -     -  # Axis/angle
    #                        -            -     -      -  vec  vec     -     -  # From/to
    #                        -            -     -      -    -    -  list     -  # XYZ
    #                        -            -     -      -    -    -     -  list  # Yaw/pitch/roll
    # Convenience forms (-: must be None, *: overwritten)
    #                      vec          num     *      *    -    -     -     -  # Axis/angle (implicit)
    #                      vec            -     *    num    -    -     -     -  # Axis/angle (explicit)
    #                      vec          vec     -      -    *    *     -     -  # From/to (implicit)
    #                      vec            -     -      -    *  vec     -     -  # From/to (explicit)
    #
    # "Vector type" is Vector, list, or tuple

    # Make sure that there are no conflicts between convenience parameters and canonical parameters
    if both(axis_or_frm, axis ): raise TypeError("axis"  " cannot be specified together with axis_or_frm")
    if both(axis_or_frm, frm  ): raise TypeError("frm"   " cannot be specified together with axis_or_frm")
    if both(angle_or_to, angle): raise TypeError("angle" " cannot be specified together with angle_or_to")
    if both(angle_or_to, to   ): raise TypeError("to"    " cannot be specified together with angle_or_to")

    # Transform the convenience forms to canonical form
    if axis_or_frm is not None:
        if not Vector.valid_type(axis_or_frm):
            raise TypeError("axis must be a vector type")

        if angle_or_to is not None:
            if number.valid(angle_or_to):
                # Axis/angle (implicit)
                axis = axis_or_frm
                angle = angle_or_to
            elif Vector.valid_type(angle_or_to):
                # From/to (implicit)
                frm = axis_or_frm
                to = angle_or_to
            else:
                raise TypeError("angle_or_to must be a number or a vector type")
        elif angle is not None:
            # Axis/angle (explicit)
            axis = axis_or_frm
        elif to is not None:
            # From/to (explicit)
            frm = axis_or_frm

    # Check the parameters that must appear in pairs
    if axis  is not None and angle is None: raise TypeError("angle" " is required when " "axis"  " is given")
    if angle is not None and axis  is None: raise TypeError("axis"  " is required when " "angle" " is given")
    if frm   is not None and to    is None: raise TypeError("to"    " is required when " "frm"   " is given")
    if to    is not None and frm   is None: raise TypeError("frm"   " is required when " "to"    " is given")

    # Handle the different cases
    if axis is not None:
        # Check that no other specification is given
        if frm is not None: raise TypeError("frm" " cannot be specified together with axis")
        if xyz is not None: raise TypeError("xyz" " cannot be specified together with axis")
        if ypr is not None: raise TypeError("ypr" " cannot be specified together with axis")

        return RotateAxisAngle(axis, angle)

    elif frm is not None:
        # Check that no other specification is given
        if axis is not None: raise TypeError("axis" " cannot be specified together with frm")
        if xyz  is not None: raise TypeError("xyz"  " cannot be specified together with frm")
        if ypr  is not None: raise TypeError("ypr"  " cannot be specified together with frm")

        return RotateFromTo(frm, to, ignore_ambiguity)

    elif xyz is not None:
        # Check that no other specification is given
        if axis is not None: raise TypeError("axis" " cannot be specified together with frm")
        if frm  is not None: raise TypeError("frm"  " cannot be specified together with axis")
        if ypr  is not None: raise TypeError("ypr"  " cannot be specified together with axis")

        return RotateXyz(*xyz)

    elif ypr is not None:
        # Check that no other specification is given
        if axis is not None: raise TypeError("axis" " cannot be specified together with frm")
        if frm  is not None: raise TypeError("frm"  " cannot be specified together with axis")
        if xyz  is not None: raise TypeError("xyz"  " cannot be specified together with axis")

        return RotateYpr(*ypr)

    else:
        raise TypeError("Invalid call signature")
Esempio n. 16
0
 def test_inverse(self):
     self.assertInverse(RotateYpr(10, 20, 30),
                        RotateYpr(0, 0, -30) * RotateYpr(0, -20, 0) *
                        RotateYpr(-10, 0, 0),
                        symmetric=False)
Esempio n. 17
0
    def test_to_matrix(self):
        # No rotation
        self.assertAlmostEqual(
            RotateYpr(0, 0, 0).to_matrix(), affine_matrix(X, Y, Z))

        # 90 degrees around a single axis
        self.assertAlmostEqual(
            RotateYpr(90, 0, 0).to_matrix(), affine_matrix(Y, -X,
                                                           Z))  # Yaw left
        self.assertAlmostEqual(
            RotateYpr(0, 90, 0).to_matrix(), affine_matrix(X, Z,
                                                           -Y))  # Pitch up
        self.assertAlmostEqual(
            RotateYpr(0, 0, 90).to_matrix(), affine_matrix(-Z, Y,
                                                           X))  # Roll right

        # 180 degrees around a single axis
        self.assertAlmostEqual(
            RotateYpr(180, 0, 0).to_matrix(), affine_matrix(-X, -Y, Z))  # Yaw
        self.assertAlmostEqual(
            RotateYpr(0, 180, 0).to_matrix(), affine_matrix(X, -Y,
                                                            -Z))  # Pitch
        self.assertAlmostEqual(
            RotateYpr(0, 0, 180).to_matrix(), affine_matrix(-X, Y, -Z))  # Roll

        # 90 degrees each around two axes
        self.assertAlmostEqual(
            RotateYpr(90, 90, 0).to_matrix(),
            affine_matrix(Y, Z, X))  # Yaw left, pitch up
        self.assertAlmostEqual(
            RotateYpr(90, 0, 90).to_matrix(),
            affine_matrix(-Z, -X, Y))  # Yaw left, roll right
        self.assertAlmostEqual(
            RotateYpr(0, 90, 90).to_matrix(),
            affine_matrix(Y, Z, X))  # Pitch up, roll right

        # 90 degrees each around all three axes
        self.assertAlmostEqual(
            RotateYpr(90, 90, 90).to_matrix(),
            affine_matrix(-X, Z, Y))  # Yaw left, pitch up, roll right
Esempio n. 18
0
 def test_repr(self):
     self.assertRepr(RotateYpr(1, 2, 3), "RotateYpr(1, 2, 3)")