Source code for _joint


class Mixin(object):

    def _send_joint(self, *args):
        return self._send_entity('Joint', *args)

    def send_hinge_joint(self,
                         body1, body2,
                         anchor,
                         axis = (0, 0, 1),
                         joint_range = None,
                         # other parameters to be added
                         ):
        """Send a hinge joint to the simulator to attach two bodies

        A hinge joint allows bodies to rotate in relation to one another
        about the specified axis. By using -1 in place of a body id tag
        the joint will connect a point in space to the other body. Specifying
        `joint_range` places stopping limits on the joint.

        Parameters
        ----------
        body1       : int
            The id tag of the first body. Specify -1 in order to set body1
            to the 'world'
        body2       : int 
            The id tag of the second body. Specify -1 in order to set body2
            to the 'world'
        anchor      : triple float
            The location of the joint.
        axis        : triple float (optional)
            The axis the bodies rotate about. (default is about the z-axis
            [0, 0, 1])
        joint_range : float or tuple (optional)
            The range of movement the joint can take in radians. The starting
            joint position is always at 0. By specifying a single value, *a*,
            the joint range becomes (*-a*, *+a*). You can also directly specify
            the low and high stops by directly specifying the tuple. (default is
            None meaning there are no stops)
        Returns
        -------
        int
            Id tag of the joint
        """

        self._assert_body(body1, 'body1')
        self._assert_body(body2, 'body2')
        
        assert not(body1 == -1 and body2 == -1), ('Both bodies cannot be the world')
        if joint_range is None:
            joint_range = (1, -1) # no stops

        try:
            len(joint_range)
        except:
            joint_range = (-joint_range, joint_range)

        assert(len(joint_range)) == 2
        assert(len(anchor)) == 3
        assert(len(axis)) == 3

        return self._send_joint("HingeJoint",
                          body1, body2,
                          anchor,
                          axis,
                          joint_range)

    def send_slider_joint(self,
                          body1, body2,
                          axis = (0, 0, 1),
                          joint_range = 0.5):
        """Send a slider joint to the simulator
    
        Slider joints allow two bodies to move linearly in relation to one
        another according to the specified axis.

        Parameters
        ----------
        body1       : int
            The id tag of the first body. Specify -1 in order to set body1
            to the 'world'
        body2       : int 
            The id tag of the second body. Specify -1 in order to set body2
            to the 'world'
        axis        : triple of floats (optional)
            The axis of the slider joint. (default is along the z-axis
            [0, 0, 1])
        joint_range : float or tuple of floats (optional)
            The limits the slider can move. By specifying a single float, *a*,
            high and low limits are create (*-a*, *a*). (default is 0.5)

        Returns
        -------
        int
            Id tag of the joint
        """

        self._assert_body(body1, 'body1')
        self._assert_body(body2, 'body2')
        if joint_range is None:
            joint_range = (1, -1) # no stops
        try:
            len(joint_range)
        except:
            joint_range = (-joint_range, joint_range)
        else:
          assert(len(joint_range)) == 2, "joint_range must have 2 entries"

        assert(joint_range[1] >= joint_range[0]) , "Slider joint cannot have infinite range"

        return self._send_joint("SliderJoint",
                          body1, body2,
                          axis,
                          joint_range)

    def send_ball_and_socket_joint(self,
                                   body1, body2,
                                   anchor = (0, 0, 1)):
        """Send a ball and socket joint to the simulator

        Ball and sockets maintain the distance between the bodies and the joint

        Parameters
        ----------
        body1       : int
            The id tag of the first body. Specify -1 in order to set body1
            to the 'world'
        body2       : int 
            The id tag of the second body. Specify -1 in order to set body2
            to the 'world'
        anchor      : triple of floats (optional)
            The absolute starting position of the joint.
        """

        self._assert_body(body1, 'body1')
        self._assert_body(body2, 'body2')

        return self._send_joint("BallAndSocketJoint",
                                body1, body2,
                                anchor)

    def send_universal_joint(self,
                             body1, body2,
                             anchor,
                             axis1=(0, 0, 1),
                             axis2=(1, 0, 0)):

        """Send a ball and socket joint to the simulator

        Universal joints allow rotation about two axes.

        Parameters
        ----------
        body1       : int
            The id tag of the first body. Specify -1 in order to set body1
            to the 'world'
        body2       : int 
            The id tag of the second body. Specify -1 in order to set body2
            to the 'world'
        anchor      : triple of floats
            The absolute starting world position of the joint.
        axis1       : triple of floats (optional)
            The first axis of rotation. (Default is (0, 0, 1))
        axis2       : triple of floats (optional)
            The second axis of rotation. (Default is (1, 0, 0))
        """

        self._assert_body(body1, 'body1')
        self._assert_body(body2, 'body2')

        return self._send_joint("UniversalJoint",
                                body1, body2,
                                anchor, axis1, axis2)

    def send_point_mass_spring_joint( self,
                                  body1, body2,
                                  resting_length = 1.0,
                                  stiffness = 1.0,
                                  damping = 0.0 ):
        """Sends a spring which simply maintains a certain length between two bodies"""

        self._assert_body( body1 )
        self._assert_body( body2 )

        return self._send_joint( 'PointMassSpringJoint',
                                 body1, body2,
                                 resting_length,
                                 stiffness, damping )

    def send_linear_spring_joint( self,
                                  body1,
                                  body2,
                                  resting_length = 1.0,
                                  stiffness = 1.0,
                                  damping = 0.0 ):
        """Sends a linear spring with infinite rotational stiffness"""

        self._assert_body( body1 )
        self._assert_body( body2 )

        return self._send_joint( 'LinearSpringJoint',
                                 body1, body2,
                                 resting_length,
                                 stiffness,
                                 damping )

    def send_hinge_spring_joint( self,
                                  body1,
                                  body2,
                                  stiffness = 1.0,
                                  axis1 = ( 0, 1, 0 ),
                                  axis2 = ( 0, 0, 1 ),
                                  damping = 0.0 ):
        """Sends a linear spring with infinite rotational stiffness"""

        self._assert_body( body1 )
        self._assert_body( body2 )

        return self._send_joint( 'HingeSpringJoint',
                                 body1, body2,
                                 stiffness,
                                 axis1, axis2,
                                 damping )

    def send_universal_spring_joint( self,
                                     body1,
                                     body2,
                                     resting_length = 1.0,
                                     linear_stiffness = 1.0,
                                     rotational_stiffness = 10.0 ):
        """Sends a spring"""

        # assert resting_length > 0, ('resting_length must be > 0' )
        # assert stiffness > 0, ( 'stiffness must be > 0' )
        self._assert_body( body1 )
        self._assert_body( body2 )

        return self._send_joint( 'UniversalSpringJoint',
                                    body1, body2,
                                    resting_length,
                                    linear_stiffness,
                                    rotational_stiffness )