Exemplo n.º 1
0
    def test_link_inertia(self):
        """
        A similar test to what is done in structure.py to test
        compound inertia, only now we do it in a link.
        :return:
        """
        # First, the comparison inertial
        total_mass = 100
        simple_box = Box(4, 8, 12, mass=total_mass)
        i1 = simple_box.get_inertial()

        # Same split as in structure.py test, only now
        # we're making sure it is distributed around the
        # origin since box inertial above is relative to
        # its center of mass
        link = Link("test_link")
        y_axis = Vector3(0, 1, 0)
        deg90 = 0.5 * math.pi

        # Split 5 / 7 in z-direction
        frac = total_mass / 12.0
        total_up = 5 * frac
        total_down = 7 * frac

        # We split the upper part 6 / 2 in the y-direction
        # and align in the center.
        frac_up = total_up / 8.0
        sub1 = Collision("sub1", geometry=Box(5, 6, 4, mass=6 * frac_up))
        sub1.rotate_around(y_axis, deg90)
        sub1.translate(Vector3(0, 1, 3.5))
        link.add_element(sub1)

        sub2 = Collision("sub2", geometry=Box(5, 2, 4, mass=2 * frac_up))
        sub2.rotate_around(y_axis, deg90)
        sub2.translate(Vector3(0, -3, 3.5))
        link.add_element(sub2)

        sub3 = Collision("sub3", geometry=Box(4, 8, 7, mass=total_down))
        sub3.translate(Vector3(0, 0, -2.5))
        link.add_element(sub3)

        link.calculate_inertial()
        self.assertEqualTensors(i1, link.inertial)
Exemplo n.º 2
0
m = Model(name="mybot")
sdf = SDF(elements=[m])

geom = Box(SENSOR_BASE_THICKNESS, SENSOR_BASE_WIDTH, SENSOR_BASE_WIDTH, MASS)
base = StructureCombination("base", geom)

x_sensors = 0.5 * (SENSOR_BASE_THICKNESS + SENSOR_THICKNESS)
y_left_sensor = -0.5 * SENSOR_WIDTH - SEPARATION
y_right_sensor = 0.5 * SENSOR_WIDTH + SEPARATION

left = StructureCombination("left", Box(SENSOR_THICKNESS, SENSOR_WIDTH, SENSOR_HEIGHT, MASS))
left.set_position(Vector3(x_sensors, y_left_sensor, 0))

right = StructureCombination("right", Box(SENSOR_THICKNESS, SENSOR_WIDTH, SENSOR_HEIGHT, MASS))
right.set_position(Vector3(x_sensors, y_right_sensor, 0))

link = Link("my_link")
link.add_elements([base, left, right])


link.align_center_of_mass()
link.calculate_inertial()

m.add_element(link)

apply_surface_parameters(m)
m.translate(Vector3(0, 0, in_mm(30)))

with open("/home/elte/.gazebo/models/test_bot/model.sdf", "w") as f:
    f.write(str(sdf))
Exemplo n.º 3
0
    def _build_body(self, traversed, model, plugin, component, link=None, child_joints=None):
        """
        :param traversed: Set of components that were already traversed,
                          prevents loops (since all connections are two-sided).
        :type traversed: set
        :param model:
        :param plugin:
        :param component:
        :type component: Component
        :param link:
        :type link: Link
        :return: The primary link used in this traversal, i.e. the link
                 passed to it or the first link created.
        """
        if component in traversed:
            return link

        create_link = link is None
        traversed.add(component)
        if create_link:
            # New tree, create a link. The component name
            # should contain the body part ID so this name should
            # be unique.
            # The position of the link is determined later when we decide
            # its center of mass.
            link = Link("link_%s" % component.name, self_collide=True)
            child_joints = []
            model.add_element(link)

        # Add this component to the link.
        position = link.to_local_frame(component.get_position())
        rotation = link.to_local_direction(component.get_rotation())
        component.set_position(position)
        component.set_rotation(rotation)
        link.add_element(component)

        # Add sensors registered on this component
        plugin.add_elements(component.get_plugin_sensors(link))

        for conn in component.connections:
            if conn.joint:
                # Create the subtree after the joint
                other_link = self._build_body(traversed, model, plugin, conn.other)
                if other_link is None:
                    # This connection was already created
                    # from the other side.
                    continue

                # Check whether this component is the parent or the child
                # of the joint connection (it is the parent by default)
                # This is relevant for another reason, because we will
                # be moving the internals of the current joint around
                # to center the inertia later on. This means that for
                # joints for which the current link is the child we need
                # to move the joint as well since the joint position is
                # expressed in the child frame. If the current link is
                # the parent there is no need to move it with this one,
                # and since `create_joint` is called after everything
                # within the child link has been fully neither does
                # the other link code.
                parent_link = link
                child_link = other_link
                is_child = conn.joint.parent is not component

                if is_child:
                    parent_link, child_link = other_link, link

                joint = conn.joint.create_joint(parent_link, child_link,
                                                conn.joint.parent, conn.joint.child)
                model.add_element(joint)

                if is_child:
                    child_joints.append(joint)
            else:
                # Just add this element to the current link
                self._build_body(traversed, model, plugin, conn.other, link, child_joints)

        if create_link:
            # Give the link the inertial properties of the combined collision,
            # only calculated by the item which created the link.
            # Note that we need to align the center of mass with the link's origin,
            # which will move the internal components around. In order to compensate
            # for this in the internal position we need to reposition the link according
            # to this change.
            translation = link.align_center_of_mass()
            link.translate(-translation)
            link.calculate_inertial()

            # Translate all the joints expressed in this link's frame that
            # were created before repositioning
            # Note that the joints need the same translation as the child elements
            # rather than the counter translation of the link.
            for joint in child_joints:
                joint.translate(translation)

        return link
Exemplo n.º 4
0
    def _build_body(self, traversed, model, plugin, component, link=None, child_joints=None):
        """
        :param traversed: Set of components that were already traversed,
                          prevents loops (since all connections are two-sided).
        :type traversed: set
        :param model:
        :param plugin:
        :param component:
        :type component: Component
        :param link:
        :type link: Link
        :return: The primary link used in this traversal, i.e. the link
                 passed to it or the first link created.
        """
        if component in traversed:
            return link

        create_link = link is None
        traversed.add(component)
        if create_link:
            # New tree, create a link. The component name
            # should contain the body part ID so this name should
            # be unique.
            # The position of the link is determined later when we decide
            # its center of mass.
            link = Link("link_%s" % component.name, self_collide=True)
            child_joints = []
            model.add_element(link)

        # Add this component to the link.
        position = link.to_local_frame(component.get_position())
        rotation = link.to_local_direction(component.get_rotation())
        component.set_position(position)
        component.set_rotation(rotation)
        link.add_element(component)

        # Add sensors registered on this component
        plugin.add_elements(component.get_plugin_sensors(link))

        for conn in component.connections:
            if conn.joint:
                # Create the subtree after the joint
                other_link = self._build_body(traversed, model, plugin, conn.other)
                if other_link is None:
                    # This connection was already created
                    # from the other side.
                    continue

                # Check whether this component is the parent or the child
                # of the joint connection (it is the parent by default)
                # This is relevant for another reason, because we will
                # be moving the internals of the current joint around
                # to center the inertia later on. This means that for
                # joints for which the current link is the child we need
                # to move the joint as well since the joint position is
                # expressed in the child frame. If the current link is
                # the parent there is no need to move it with this one,
                # and since `create_joint` is called after everything
                # within the child link has been fully neither does
                # the other link code.
                parent_link = link
                child_link = other_link
                is_child = conn.joint.parent is not component

                if is_child:
                    parent_link, child_link = other_link, link

                joint = conn.joint.create_joint(parent_link, child_link,
                                                conn.joint.parent, conn.joint.child)
                model.add_element(joint)

                if is_child:
                    child_joints.append(joint)
            else:
                # Just add this element to the current link
                self._build_body(traversed, model, plugin, conn.other, link, child_joints)

        if create_link:
            # Give the link the inertial properties of the combined collision,
            # only calculated by the item which created the link.
            # Note that we need to align the center of mass with the link's origin,
            # which will move the internal components around. In order to compensate
            # for this in the internal position we need to reposition the link according
            # to this change.
            translation = link.align_center_of_mass()
            link.translate(-translation)
            link.calculate_inertial()

            # Translate all the joints expressed in this link's frame that
            # were created before repositioning
            # Note that the joints need the same translation as the child elements
            # rather than the counter translation of the link.
            for joint in child_joints:
                joint.translate(translation)

        return link