Beispiel #1
0
def create_hinge_scene():
    size = [0.5, 0.25, 1]
    b1, b2 = create_bodies([0, 0, 0], [0, 0, -2.5], size)

    demoutils.sim().add(b1)
    demoutils.sim().add(b2)

    f1 = agx.Frame()
    f1.setLocalTranslate(0, 0, size[2])
    f1.setLocalRotate(agx.EulerAngles(0, math.radians(90), 0))

    hinge1 = agx.Hinge(b1, f1)
    demoutils.sim().add(hinge1)

    # Make the first motor swing back and forth
    speed_controller = AlternatingSpeedController(hinge1.getMotor1D(), 1, 2)
    demoutils.sim().add(speed_controller)

    distance = (b2.getPosition() - b1.getPosition()).length()
    f1 = agx.Frame()
    f1.setLocalTranslate(0, 0, -distance / 2)
    f1.setLocalRotate(agx.EulerAngles(0, math.radians(90), 0))

    f2 = agx.Frame()
    f2.setLocalTranslate(0, 0, distance / 2)
    f2.setLocalRotate(agx.EulerAngles(0, math.radians(90), 0))

    hinge2 = agx.Hinge(b1, f1, b2, f2)
    demoutils.sim().add(hinge2)
def seesaw(sim, root, pos, angle, h=0.08):
    d = 0.8
    # Sides
    dims = [0.6*(width/14), 0.15*(width/14), h*3/2]
    pos_s = [pos[0]+(d/2+0.3)*np.cos(angle)*(width/14), pos[1]+(d/2+0.3)*np.sin(angle)*(width/14), pos[2]+h/2]
    sideP = addboxx(sim, root, dims, pos_s)
    dims = [0.6*(width/14), 0.15*(width/14), h*3/2]
    pos_s = [pos[0]-(d/2+0.3)*np.cos(angle)*(width/14), pos[1]-(d/2+0.3)*np.sin(angle)*(width/14), pos[2]+h/2]
    sideN = addboxx(sim, root, dims, pos_s)
    # Main board
    dims = [d*(width/14), 0.9*(width/14), 0.004]
    pos_s = [pos[0]+0.06*np.sin(angle)*(width/14), pos[1]-0.06*np.cos(angle)*(width/14), pos[2]+h]
    board = addboxx(sim, root, dims, pos_s, Fixed=False)

    sideP.setRotation(agx.Quat(angle, agx.Vec3(0,0,1)))
    sideN.setRotation(agx.Quat(angle, agx.Vec3(0,0,1)))
    board.setRotation(agx.Quat(angle, agx.Vec3(0,0,1)))

    #Some stops under
    bot_tilt = 0.17
    dims = [d, 0.43, 0.004]
    dif = 0.215*np.cos(bot_tilt)*(width/14)-0.002*np.sin(bot_tilt)*(width/14)
    pos_s = [pos[0]+(0.06+dif)*np.sin(angle)*(width/14), pos[1]-(0.06+dif)*np.cos(angle)*(width/14), pos[2]+np.sin(bot_tilt)*dif]
    bottom1 = addboxx(sim, root, dims, pos_s, color=agxRender.Color.DarkGray())
    pos_s = [pos[0]+(0.06-dif)*np.sin(angle)*(width/14), pos[1]-(0.06-dif)*np.cos(angle)*(width/14), pos[2]+np.sin(bot_tilt)*dif]
    bottom2 = addboxx(sim, root, dims, pos_s, color=agxRender.Color.DarkGray())

    
    bottom1.setRotation(agx.Quat( bot_tilt, agx.Vec3(1,0,0)))
    bottom1.setRotation(bottom1.getRotation()*agx.Quat(angle, agx.Vec3(0,0,1)))
    
    bottom2.setRotation(agx.Quat(-bot_tilt, agx.Vec3(1,0,0)))
    bottom2.setRotation(bottom2.getRotation()*agx.Quat(angle, agx.Vec3(0,0,1)))
    

    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3( np.cos(angle),np.sin(angle),0))
    hf.setCenter(agx.Vec3(pos[0]+(d/2)*np.cos(angle)*(width/14), pos[1]+(d/2)*np.sin(angle)*(width/14), pos[2]+h))
    axleP = agx.Hinge(hf, board, sideP)
    sim.add(axleP)

    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(  np.cos(angle),np.sin(angle),0))
    hf.setCenter(agx.Vec3(pos[0]*(width/14)-(d/2)*np.cos(angle)*(width/14), pos[1]*(width/14)-(d/2)*np.sin(angle)*(width/14), pos[2]+h))
    axleN = agx.Hinge(hf, board, sideN)
    sim.add(axleN)
def LinkBodies_Hinge(body1, body2, link_position, link_direction, MiroSystem=False):
    hf = agx.HingeFrame()
    hf.setAxis(agxVecify(link_direction))
    hf.setCenter(agxVecify(link_position))
    link = agx.Hinge(hf, body1, body2)
    # The line below is disabled because it messes up the steering of the example bot. 
    # link.setSolveType(agx.Constraint.DIRECT_AND_ITERATIVE)
    if MiroSystem:
        MiroSystem.Add(link)
    return link
Beispiel #4
0
    def connect(self, simulation, body1, body2, pos, axis, hingeRange):
        assert (body1 and body2)
        f1 = agx.Frame()
        f2 = agx.Frame()
        agx.Constraint.calculateFramesFromWorld(pos, axis, body1, f1, body2,
                                                f2)
        hinge = agx.Hinge(body1, f1, body2, f2)
        if hingeRange:
            hinge.getRange1D().setEnable(True)
            hinge.getRange1D().setRange(hingeRange)

        simulation.add(hinge)
        return hinge
    def buildScene1(self, app, sim, root):

        # Create the Terrain
        num_cells_x = 80
        num_cells_y = 80
        cell_size = 0.15
        max_depth = 1.0

        agx_heightField = agxCollide.HeightField(num_cells_x, num_cells_y,
                                                 (num_cells_x - 1) * cell_size,
                                                 (num_cells_y - 1) * cell_size)

        # Define the initial height field (random or fixed) depending on if if data collection or test
        if self.control_mode == "data_collection":
            np_heightField = self.createRandomHeightfield(
                num_cells_x, num_cells_y, cell_size)
        elif self.control_mode == "mpcc" or self.control_mode == "trajectory_control":
            np_heightField = self.createRandomHeightfield(
                num_cells_x, num_cells_y, cell_size)

        if self.set_height_from_previous:
            agx_heightField = self.agx_heightField_previous
        else:
            agx_heightField = self.setHeightField(agx_heightField,
                                                  np_heightField)

        terrain = agxTerrain.Terrain.createFromHeightField(
            agx_heightField, 5.0)
        sim.add(terrain)

        # Define Gravity
        G = agx.Vec3(0, 0, -10.0)
        sim.setUniformGravity(G)

        # define the material
        terrain.loadLibraryMaterial("sand_1")

        terrainMaterial = terrain.getTerrainMaterial()
        terrainMaterial.getBulkProperties().setSwellFactor(1.00)

        compactionProperties = terrainMaterial.getCompactionProperties()
        compactionProperties.setAngleOfReposeCompactionRate(500.0)

        terrain.setCompaction(1.05)

        # The trenching will reach the bounds of the terrain so we simply remove particles out of bounds
        # to get rid of the mateiral in a practical way.
        terrain.getProperties().setDeleteSoilParticlesOutsideBounds(True)

        if app:
            # Setup a renderer for the terrain
            renderer = agxOSG.TerrainVoxelRenderer(terrain, root)

            renderer.setRenderHeightField(True)
            # We choose to render the compaction of the soil to visually denote excavated
            # soil from compacted ground
            # renderer.setRenderCompaction( True, agx.RangeReal( 1.0, 1.05 ) )
            renderer.setRenderHeights(True, agx.RangeReal(-0.4, 0.1))
            # renderer.setRenderHeights(True, agx.RangeReal(-0.5,0.5))
            renderer.setRenderVoxelSolidMass(False)
            renderer.setRenderVoxelFluidMass(False)
            renderer.setRenderNodes(False)
            renderer.setRenderVoxelBoundingBox(False)
            renderer.setRenderSoilParticlesMesh(True)

            sim.add(renderer)

        # Set contact materials of the terrain and shovel
        # This contact material governs the resistance that the shovel will feel when digging into the terrain
        # [ Shovel - Terrain ] contact material
        shovelMaterial = agx.Material("shovel_material")

        terrainMaterial = terrain.getMaterial(
            agxTerrain.Terrain.MaterialType_TERRAIN)
        shovelTerrainContactMaterial = agx.ContactMaterial(
            shovelMaterial, terrainMaterial)
        shovelTerrainContactMaterial.setYoungsModulus(1e8)
        shovelTerrainContactMaterial.setRestitution(0.0)
        shovelTerrainContactMaterial.setFrictionCoefficient(0.4)
        sim.add(shovelTerrainContactMaterial)

        # Create the trenching shovel body creation, do setup in the Terrain object and
        # constrain it to a kinematic that will drive the motion

        # Create the bucket rigid body
        cuttingEdge, topEdge, forwardVector, bucket = self.createBucket(
            default)

        sim.add(bucket)

        # Create the Shovel object using the previously defined cutting and top edge
        shovel = agxTerrain.Shovel(bucket, topEdge, cuttingEdge, forwardVector)
        agxUtil.setBodyMaterial(bucket, shovelMaterial)

        # Set a margin around the bounding box of the shovel where particles are not to be merged
        shovel.setNoMergeExtensionDistance(0.1)

        # Add the shovel to the terrain
        terrain.add(shovel)

        if app:  # and self.consecutive_scoop_i < 4:
            # Create visual representation of the shovel
            node = agxOSG.createVisual(bucket, root)
            agxOSG.setDiffuseColor(node, agxRender.Color.Gold())
            agxOSG.setAlpha(node, 1.0)

        # Set initial bucket rotation
        if self.control_mode == "mpcc":
            angle_bucket_initial = -0.3 * np.pi
        else:
            angle_bucket_initial = np.random.uniform(low=-0.25 * np.pi,
                                                     high=-0.35 * np.pi)

        bucket.setRotation(agx.EulerAngles(0.0, angle_bucket_initial, agx.PI))

        # Get the offset of the bucket tip from the COM
        tip_offset = shovel.getCuttingEdgeWorld().p2

        #
        inertia_tensor = bucket.getMassProperties().getInertiaTensor()
        mass = bucket.getMassProperties().getMass()
        h_offset_sqrd = tip_offset[0]**2 + tip_offset[2]**2
        inertia_bucket = inertia_tensor.at(1, 1) + mass * h_offset_sqrd

        # Set initial bucket position (for consecutive scoops)
        if self.control_mode == "mpcc" or self.control_mode == "trajectory_control":

            if self.consecutive_scoop_i == 0:
                x_initial_tip = -4.0
            elif self.consecutive_scoop_i == 1:
                x_initial_tip = -3.6
            elif self.consecutive_scoop_i == 2:
                x_initial_tip = -3.3
            else:
                x_initial_tip = -2.6
        else:
            x_initial_tip = np.random.uniform(low=-4.5, high=-3.0)

        # find the soil height at the initial penetration location
        hf_grid_initial = terrain.getClosestGridPoint(
            agx.Vec3(x_initial_tip, 0.0, 0.0))
        height_initial = terrain.getHeight(hf_grid_initial) - 0.05

        # Set the initial bucket location such that it is just contacting the soil
        position = agx.Vec3(x_initial_tip - tip_offset[0], 0,
                            height_initial - tip_offset[2])
        bucket.setPosition(terrain.getTransform().transformPoint(position))

        bucket.setVelocity(0.0, 0.0, 0.0)
        # bucket.setAngularVelocity(0.0, 0.05, 0.0)

        # Add a lockjoint between a kinematic sphere and the shovel
        # in order to have some compliance when moving the shovel
        # through the terrain
        offset = agx.Vec3(0.0, 0.0, 0.0)

        ## ADD ALL THE JOINTS TO CONTROL THE BUCKET (x,z,theta)
        sphere1 = agx.RigidBody(agxCollide.Geometry(agxCollide.Sphere(.1)))
        sphere2 = agx.RigidBody(agxCollide.Geometry(agxCollide.Sphere(.1)))
        sphere3 = agx.RigidBody(agxCollide.Geometry(agxCollide.Sphere(.1)))

        sphere1.setMotionControl(agx.RigidBody.DYNAMICS)
        sphere2.setMotionControl(agx.RigidBody.DYNAMICS)
        sphere3.setMotionControl(agx.RigidBody.DYNAMICS)

        sphere1.getGeometries()[0].setEnableCollisions(False)
        sphere2.getGeometries()[0].setEnableCollisions(False)
        sphere3.getGeometries()[0].setEnableCollisions(False)

        tip_position = shovel.getCuttingEdgeWorld().p2
        tip_position[1] = bucket.getCmPosition()[1]

        sphere1.setPosition(tip_position)
        sphere2.setPosition(tip_position)
        sphere3.setPosition(tip_position)

        sphere1.getMassProperties().setMass(0.000001)
        sphere2.getMassProperties().setMass(0.000001)
        sphere3.getMassProperties().setMass(0.000001)

        # print('sphere mass: ', sphere1.getMassProperties().getMass())

        sim.add(sphere1)
        sim.add(sphere2)
        sim.add(sphere3)

        # Set prismatic joint for x transalation world - sphere 1
        f1 = agx.Frame()
        f1.setLocalRotate(agx.EulerAngles(0, math.radians(90), 0))
        prismatic1 = agx.Prismatic(sphere1, f1)

        # Set prismatic joint for z transalation world - sphere 2
        f1 = agx.Frame()
        f2 = agx.Frame()
        f1.setLocalRotate(agx.EulerAngles(0, math.radians(180), 0))
        f2.setLocalRotate(agx.EulerAngles(0, math.radians(180), 0))
        prismatic2 = agx.Prismatic(sphere1, f1, sphere2, f2)

        # # Set hinge joint for rotation of the bucket
        f1 = agx.Frame()
        f1.setLocalRotate(agx.EulerAngles(-math.radians(90), 0, 0))
        f2 = agx.Frame()
        f2.setLocalRotate(agx.EulerAngles(-math.radians(90), 0, 0))
        hinge2 = agx.Hinge(sphere2, f1, sphere3, f2)

        sim.add(prismatic1)
        sim.add(prismatic2)
        sim.add(hinge2)

        lock = agx.LockJoint(sphere3, bucket)
        sim.add(lock)

        # Uncomment to lock rotations
        # sim.add(agx.LockJoint(sphere2,bucket))

        # constant force and torque
        operations = [agx.Vec3(0.0, 0.0, 0.0), agx.Vec3(0.0, 0.0, 0.0)]

        # Extract soil shape along the bucket excavation direction
        x_hf, z_hf = self.extractSoilSurface(terrain, sim)
        self.soilShapeEvaluator = SoilSurfaceEvaluator(x_hf, z_hf)
        setattr(self.dfl, "soilShapeEvaluator", self.soilShapeEvaluator)

        if self.control_mode == "data_collection":

            # create driver and add it to the simulation
            driver = ForceDriverPID(app, sphere3, lock, hinge2, prismatic1,
                                    prismatic2, terrain, shovel, operations,
                                    self.dt_control)

            # Add the current surface evaluator to the controller
            setattr(driver, "soilShapeEvaluator", self.soilShapeEvaluator)

            # Add the controller to the simulation
            sim.add(driver)

        elif self.control_mode == "trajectory_control":
            # create driver and add it to the simulation
            # create driver and add it to the simulation
            driver = ForceDriverTrajectory(app, sphere3, lock, hinge2,
                                           prismatic1, prismatic2, terrain,
                                           shovel, operations, self.dt_control)

            # Add the current surface evaluator to the controller
            setattr(driver, "soilShapeEvaluator", self.soilShapeEvaluator)
            setattr(driver, "dfl", self.dfl)

            x_path = x_initial_tip + np.array(
                [0., 0.5, 1.5, 2.0, 2.5, 3.0, 3.5])
            y_soil, _, _, _ = self.soilShapeEvaluator.soil_surf_eval(x_path)
            y_path = y_soil + np.array(
                [-0.07, -0.25, -0.25, -0.25, -0.25, -0.25, -0.02])
            spl_path = spline_path(x_path, y_path)
            setattr(driver, "path_eval", spl_path.path_eval)

            # Add the controller to the simulation
            sim.add(driver)

        elif self.control_mode == "mpcc":
            # create driver and add it to the simulation
            driver = ForceDriverDFL(app, sphere3, lock, hinge2, terrain,
                                    shovel, self.dt_control)

            ################ MPCC CONTROLLER ############################
            # Add the current surface evaluator to the controller
            setattr(driver, "soilShapeEvaluator", self.soilShapeEvaluator)
            setattr(driver, "dfl", self.dfl)
            setattr(driver, "scaling", self.scaling)

            x_path = x_initial_tip + np.array([
                0.,
                0.5,
                1.5,
                2.0,
                2.5,
                3.0,
            ])

            y_soil, _, _, _ = self.soilShapeEvaluator.soil_surf_eval(x_path)
            y_path = y_soil + np.array(
                [-0.07, -0.25, -0.25, -0.25, -0.25, -0.02])

            # Set the state constraints
            if self.observable_type == "dfl":

                x_min = np.array([
                    x_initial_tip - 0.1, -3., 0.5, -0.5, -2.5, -2.5,
                    -80000 * self.scaling, -80000 * self.scaling, 0.0,
                    -70000 * self.scaling, -70000 * self.scaling,
                    -70000 * self.scaling, -70000 * self.scaling
                ])
                x_max = np.array([
                    2., 5.0, 2.5, 2.5, 2.5, 2.5, 80000 * self.scaling,
                    80000 * self.scaling, 3000. * self.scaling,
                    70000 * self.scaling, 70000 * self.scaling,
                    70000 * self.scaling, 70000 * self.scaling
                ])
                n_dyn = self.dfl.plant.n

            elif self.observable_type == "x":

                x_min = np.array(
                    [x_initial_tip - 0.1, -3., 0.5, -0.5, -2.5, -2.5])
                x_max = np.array([2., 5.0, 2.5, 2.5, 2.5, 2.5])
                n_dyn = self.dfl.plant.n_x

            # Set the input constraints
            u_min = np.array([
                -100. * self.scaling, -70000 * self.scaling,
                -70000 * self.scaling
            ])
            u_max = np.array([
                75000. * self.scaling, 70000 * self.scaling,
                70000 * self.scaling
            ])

            if self.set_height_from_previous:
                pass
            else:
                self.spl_path = spline_path(x_path, y_path)

            # instantiate the MPCC object

            mpcc = MPCC(np.zeros((n_dyn, n_dyn)),
                        np.zeros((n_dyn, self.dfl.plant.n_u)),
                        x_min,
                        x_max,
                        u_min,
                        u_max,
                        dt=self.dt_data,
                        N=50)

            #  set the observation function, path object and linearization function
            setattr(mpcc, "path_eval", self.spl_path.path_eval)
            setattr(mpcc, "get_soil_surface",
                    self.soilShapeEvaluator.soil_surf_eval)

            if self.model_has_surface_shape:
                print('Linearizing with soil shape')
                setattr(mpcc, "get_linearized_model",
                        self.dfl.linearize_soil_dynamics_koop)
            else:
                setattr(mpcc, "get_linearized_model",
                        self.dfl.linearize_soil_dynamics_no_surface)

            self.mpcc = copy.copy(mpcc)

            pos_tip, vel_tip, acl_tip, ang_tip, omega, alpha = measureBucketState(
                sphere3, shovel)

            x_i = np.array([
                pos_tip[0], pos_tip[2], ang_tip, vel_tip[0], vel_tip[2],
                omega[1]
            ])
            eta_i = np.array(
                [acl_tip[0], acl_tip[2], alpha[1], 0., 0., 0., 0.])

            # Choose the initial path arcposition based on a close initial x tip position
            theta_array = np.linspace(-10, 0, num=1000)
            for i in range(len(theta_array)):
                x_path, y_path = self.spl_path.path_eval(theta_array[i], d=0)
                if x_path > pos_tip[0]:
                    path_initial = theta_array[i]
                    break

            # set initial input (since input cost is differential)
            x_0_mpcc = np.concatenate(
                (self.dfl.g_Koop(x_i, eta_i, _), np.array([path_initial])))
            u_minus_mpcc = np.array([0.0, 0.0, 0.0, 0.0])
            driver.last_x_opt = x_0_mpcc

            # sets up the new mpcc problem _mpcc
            mpcc.setup_new_problem(self.Q_mpcc, self.R_mpcc, self.q_theta_mpcc,
                                   x_0_mpcc, u_minus_mpcc)

            setattr(driver, "mpcc", mpcc)
            #####################################################################################
            # Add the controller to the simulation
            sim.add(driver)

        # Limit core usage to number of physical cores. Assume that HT/SMT is active
        # and divide max threads with 2.
        agx.setNumThreads(0)
        n = int(agx.getNumThreads() / 2 - 1)
        agx.setNumThreads(n)

        # Setup initial camera view
        if app:
            createHelpText(sim, app)

        return terrain, shovel, driver, sphere3
Beispiel #6
0
def create_gripper_peg_in_hole(sim=None,
                               name="",
                               material=None,
                               position=agx.Vec3(0.0, 0.0, 0.0),
                               geometry_transform=agx.AffineMatrix4x4(),
                               geometry_scaling=agx.Matrix3x3(agx.Vec3(0.045)),
                               joint_ranges=None,
                               force_ranges=None):

    # Create gripper object
    gripper_mesh = agxUtil.createTrimeshFromWavefrontOBJ(
        MESH_GRIPPER_FILE, agxCollide.Trimesh.NO_WARNINGS, geometry_scaling)
    gripper_geom = agxCollide.Geometry(
        gripper_mesh,
        agx.AffineMatrix4x4.rotate(agx.Vec3(0, 1, 0), agx.Vec3(0, 0, 1)))
    gripper_body = agx.RigidBody(name + "_body")
    gripper_body.add(gripper_geom)
    gripper_body.setMotionControl(agx.RigidBody.DYNAMICS)
    gripper_body.setPosition(position)
    gripper_body.setCmRotation(agx.EulerAngles(0.0, np.pi, 0.0))
    if material is not None:
        gripper_geom.setMaterial(material)
    sim.add(gripper_body)

    # Add kinematic structure
    rotation_y_to_z = agx.OrthoMatrix3x3()
    rotation_y_to_z.setRotate(agx.Vec3.Y_AXIS(), agx.Vec3.Z_AXIS())
    rotation_y_to_x = agx.OrthoMatrix3x3()
    rotation_y_to_x.setRotate(agx.Vec3.Y_AXIS(), agx.Vec3.X_AXIS())

    base_z = create_body(name=name + "_base_z",
                         shape=agxCollide.Cylinder(0.005, 0.025),
                         position=position,
                         rotation=rotation_y_to_z,
                         motion_control=agx.RigidBody.DYNAMICS,
                         disable_collisions=True)
    sim.add(base_z)

    base_y = create_body(name=name + "_base_y",
                         shape=agxCollide.Cylinder(0.005, 0.025),
                         position=position,
                         motion_control=agx.RigidBody.DYNAMICS,
                         disable_collisions=True)
    sim.add(base_y)

    base_x = create_body(name=name + "_base_x",
                         shape=agxCollide.Cylinder(0.005, 0.025),
                         position=position,
                         rotation=rotation_y_to_x,
                         motion_control=agx.RigidBody.DYNAMICS,
                         disable_collisions=True)
    sim.add(base_x)

    base_x_body = base_x.getRigidBody("gripper_base_x")
    base_y_body = base_y.getRigidBody("gripper_base_y")
    base_z_body = base_z.getRigidBody("gripper_base_z")

    base_x_body.getGeometry("gripper_base_x").setEnableCollisions(False)
    base_y_body.getGeometry("gripper_base_y").setEnableCollisions(False)
    base_z_body.getGeometry("gripper_base_z").setEnableCollisions(False)

    # Add prismatic joints between bases
    joint_base_x = agx.Prismatic(agx.Vec3(1, 0, 0), base_x_body)
    joint_base_x.setEnableComputeForces(True)
    joint_base_x.setEnable(True)
    joint_base_x.setName(name + "_joint_base_x")
    sim.add(joint_base_x)

    joint_base_y = agx.Prismatic(agx.Vec3(0, 1, 0), base_x_body, base_y_body)
    joint_base_y.setEnableComputeForces(True)
    joint_base_y.setEnable(True)
    joint_base_y.setName(name + "_joint_base_y")
    sim.add(joint_base_y)

    joint_base_z = agx.Prismatic(agx.Vec3(0, 0, -1), base_y_body, base_z_body)
    joint_base_z.setEnableComputeForces(True)
    joint_base_z.setEnable(True)
    joint_base_z.setName(name + "_joint_base_z")
    sim.add(joint_base_z)

    # Hinge joint to rotate gripper around y axis
    hf = agx.HingeFrame()
    hf.setCenter(position)
    hf.setAxis(agx.Vec3(0, 1, 0))
    joint_rot_y = agx.Hinge(hf, base_z_body, gripper_body)
    joint_rot_y.setEnableComputeForces(True)
    joint_rot_y.setName(name + "_joint_rot_y")
    sim.add(joint_rot_y)

    # Set joint ranges
    if joint_ranges is not None:
        # x range
        joint_base_x_range_controller = joint_base_x.getRange1D()
        joint_base_x_range_controller.setRange(joint_ranges["t_x"][0],
                                               joint_ranges["t_x"][1])
        joint_base_x_range_controller.setEnable(True)

        # y range
        joint_base_y_range_controller = joint_base_y.getRange1D()
        joint_base_y_range_controller.setRange(joint_ranges["t_y"][0],
                                               joint_ranges["t_y"][1])
        joint_base_y_range_controller.setEnable(True)

        # z range
        joint_base_z_range_controller = joint_base_z.getRange1D()
        joint_base_z_range_controller.setRange(joint_ranges["t_z"][0],
                                               joint_ranges["t_z"][1])
        joint_base_z_range_controller.setEnable(True)

        # rot y
        joint_rot_y_range_controller = joint_rot_y.getRange1D()
        joint_rot_y_range_controller.setRange(joint_ranges["r_y"][0],
                                              joint_ranges["r_y"][1])
        joint_rot_y_range_controller.setEnable(True)

    # Enable motors
    joint_base_x_motor = joint_base_x.getMotor1D()
    joint_base_x_motor.setEnable(True)
    joint_base_x_motor.setLockedAtZeroSpeed(False)

    joint_base_y_motor = joint_base_y.getMotor1D()
    joint_base_y_motor.setEnable(True)
    joint_base_y_motor.setLockedAtZeroSpeed(False)

    joint_base_z_motor = joint_base_z.getMotor1D()
    joint_base_z_motor.setEnable(True)
    joint_base_z_motor.setLockedAtZeroSpeed(False)

    joint_rot_y_motor = joint_rot_y.getMotor1D()
    joint_rot_y_motor.setEnable(True)
    joint_rot_y_motor.setLockedAtZeroSpeed(False)

    # Set max forces in motors
    if force_ranges is not None:
        # force x
        joint_base_x_motor.setForceRange(force_ranges['t_x'][0],
                                         force_ranges['t_x'][1])

        # force y
        joint_base_y_motor.setForceRange(force_ranges['t_y'][0],
                                         force_ranges['t_y'][1])

        # force z
        joint_base_z_motor.setForceRange(force_ranges['t_z'][0],
                                         force_ranges['t_z'][1])

        # force rotation around y
        joint_rot_y_motor.setForceRange(force_ranges['r_y'][0],
                                        force_ranges['r_y'][1])
Beispiel #7
0
def build_simulation(goal=False):
    """Builds simulations for both start and goal configurations
    :param bool goal: toggles between simulation definition of start and goal configurations
    :return agxSDK.Simulation: simulation object
    """
    assembly_name = "start_"
    goal_string = ""
    if goal:
        assembly_name = "goal_"
        goal_string = "_goal"

    # Instantiate a simulation
    sim = agxSDK.Simulation()

    # By default, the gravity vector is 0,0,-9.81 with a uniform gravity field. (we CAN change that
    # too by creating an agx.PointGravityField for example).
    # AGX uses a right-hand coordinate system (That is Z defines UP. X is right, and Y is into the screen)
    if not GRAVITY:
        logger.info("Gravity off.")
        g = agx.Vec3(0, 0, 0)  # remove gravity
        sim.setUniformGravity(g)

    # Get current delta-t (timestep) that is used in the simulation?
    dt = sim.getTimeStep()
    logger.debug("default dt = {}".format(dt))

    # Change the timestep
    sim.setTimeStep(TIMESTEP)

    # Confirm timestep changed
    dt = sim.getTimeStep()
    logger.debug("new dt = {}".format(dt))

    # Create a new empty Assembly
    scene = agxSDK.Assembly()
    scene.setName(assembly_name + "assembly")

    # Add start assembly to simulation
    sim.add(scene)

    # Create a ground plane for reference
    if not goal:
        ground = create_body(name="ground", shape=agxCollide.Box(LENGTH, LENGTH, GROUND_WIDTH),
                             position=agx.Vec3(LENGTH / 2, 0, -(GROUND_WIDTH + SIZE_GRIPPER / 2 + LENGTH)),
                             motion_control=agx.RigidBody.STATIC)
        scene.add(ground)

    # Create cable
    cable = agxCable.Cable(RADIUS, RESOLUTION)
    cable.setName("DLO" + goal_string)

    gripper_left = create_body(name="gripper_left" + goal_string,
                               shape=agxCollide.Box(SIZE_GRIPPER, SIZE_GRIPPER, SIZE_GRIPPER),
                               position=agx.Vec3(0, 0, 0), motion_control=agx.RigidBody.DYNAMICS)
    scene.add(gripper_left)

    gripper_right = create_body(name="gripper_right" + goal_string,
                                shape=agxCollide.Box(SIZE_GRIPPER, SIZE_GRIPPER, SIZE_GRIPPER),
                                position=agx.Vec3(LENGTH, 0, 0),
                                motion_control=agx.RigidBody.DYNAMICS)
    scene.add(gripper_right)

    # Disable collisions for grippers
    gripper_left_body = scene.getRigidBody("gripper_left" + goal_string)
    gripper_left_body.getGeometry("gripper_left" + goal_string).setEnableCollisions(False)
    gripper_right_body = scene.getRigidBody("gripper_right" + goal_string)
    gripper_right_body.getGeometry("gripper_right" + goal_string).setEnableCollisions(False)

    logger.info("Mass of grippers: {}".format(scene.getRigidBody("gripper_right" + goal_string).calculateMass()))

    # Create Frames for each gripper:
    # Cables are attached passing through the attachment point along the Z axis of the body's coordinate frame.
    # The translation specified in the transformation is relative to the body and not the world
    left_transform = agx.AffineMatrix4x4()
    left_transform.setTranslate(SIZE_GRIPPER + RADIUS, 0, 0)
    left_transform.setRotate(agx.Vec3.Z_AXIS(), agx.Vec3.Y_AXIS())  # Rotation matrix which switches Z with Y
    frame_left = agx.Frame(left_transform)

    right_transform = agx.AffineMatrix4x4()
    right_transform.setTranslate(- SIZE_GRIPPER - RADIUS, 0, 0)
    right_transform.setRotate(agx.Vec3.Z_AXIS(), -agx.Vec3.Y_AXIS())  # Rotation matrix which switches Z with -Y
    frame_right = agx.Frame(right_transform)

    cable.add(agxCable.FreeNode(agx.Vec3(SIZE_GRIPPER + RADIUS, 0, 0)))  # Fix cable to gripper_left
    cable.add(agxCable.FreeNode(agx.Vec3(LENGTH - SIZE_GRIPPER - RADIUS, 0, 0)))  # Fix cable to gripper_right

    # Try to initialize cable
    report = cable.tryInitialize()
    if report.successful():
        logger.debug("Successful cable initialization.")
    else:
        logger.error(report.getActualError())

    actual_length = report.getLength()
    logger.info("Actual length: " + str(actual_length))

    # Add cable plasticity
    plasticity = agxCable.CablePlasticity()
    plasticity.setYieldPoint(YIELD_POINT, agxCable.BEND)  # set torque required for permanent deformation
    cable.addComponent(plasticity)  # NOTE: Stretch direction is always elastic

    # Define material
    material = agx.Material("Aluminum")
    bulk_material = material.getBulkMaterial()
    bulk_material.setPoissonsRatio(POISSON_RATIO)
    bulk_material.setYoungsModulus(YOUNG_MODULUS)
    cable.setMaterial(material)

    # Add cable to simulation
    scene.add(cable)

    # Add segment names and get first and last segment
    count = 1
    iterator = cable.begin()
    segment_left = iterator.getRigidBody()
    segment_left.setName('dlo_' + str(count) + goal_string)
    while not iterator.isEnd():
        count += 1
        segment_right = iterator.getRigidBody()
        segment_right.setName('dlo_' + str(count) + goal_string)
        iterator.inc()

    # Add hinge constraints
    hinge_joint_left = agx.Hinge(scene.getRigidBody("gripper_left" + goal_string), frame_left, segment_left)
    hinge_joint_left.setName('hinge_joint_left' + goal_string)
    motor_left = hinge_joint_left.getMotor1D()
    motor_left.setEnable(True)
    motor_left_param = motor_left.getRegularizationParameters()
    motor_left_param.setCompliance(1e12)
    motor_left.setLockedAtZeroSpeed(False)
    lock_left = hinge_joint_left.getLock1D()
    lock_left.setEnable(False)
    # Set range of hinge joint
    # range_left = hinge_joint_left.getRange1D()
    # range_left.setEnable(True)
    # range_left.setRange(agx.RangeReal(-math.pi / 2, math.pi / 2))
    scene.add(hinge_joint_left)

    hinge_joint_right = agx.Hinge(scene.getRigidBody("gripper_right" + goal_string), frame_right, segment_right)
    hinge_joint_right.setName('hinge_joint_right' + goal_string)
    motor_right = hinge_joint_right.getMotor1D()
    motor_right.setEnable(True)
    motor_right_param = motor_right.getRegularizationParameters()
    motor_right_param.setCompliance(1e12)
    motor_right.setLockedAtZeroSpeed(False)
    lock_right = hinge_joint_right.getLock1D()
    lock_right.setEnable(False)
    # Set range of hinge joint
    # range_right = hinge_joint_right.getRange1D()
    # range_right.setEnable(True)
    # range_right.setRange(agx.RangeReal(-math.pi / 2, math.pi / 2))
    scene.add(hinge_joint_right)

    # Create base for gripper motors
    prismatic_base_right = create_locked_prismatic_base("gripper_right" + goal_string, gripper_right_body, compliance=0,
                                                        motor_ranges=[(-FORCE_RANGE, FORCE_RANGE),
                                                                      (-FORCE_RANGE, FORCE_RANGE),
                                                                      (-FORCE_RANGE, FORCE_RANGE)],
                                                        position_ranges=[
                                                            (-LENGTH + 2 * (2 * RADIUS + SIZE_GRIPPER),
                                                             0),
                                                            (-LENGTH, LENGTH),
                                                            (-LENGTH, LENGTH)],
                                                        compute_forces=True,
                                                        lock_status=[False, False, False])
    scene.add(prismatic_base_right)
    prismatic_base_left = create_locked_prismatic_base("gripper_left" + goal_string, gripper_left_body, compliance=0,
                                                       lock_status=[True, True, True])
    scene.add(prismatic_base_left)

    return sim
Beispiel #8
0
def build_simulation(goal=False):
    """Builds simulations for both start and goal configurations
    :param bool goal: toggles between simulation definition of start and goal configurations
    :return agxSDK.Simulation: simulation object
    """
    assembly_name = "start_"
    goal_string = ""
    if goal:
        assembly_name = "goal_"
        goal_string = "_goal"

    # Instantiate a simulation
    sim = agxSDK.Simulation()

    # By default, the gravity vector is 0,0,-9.81 with a uniform gravity field. (we CAN change that
    # too by creating an agx.PointGravityField for example).
    # AGX uses a right-hand coordinate system (That is Z defines UP. X is right, and Y is into the screen)
    if not GRAVITY:
        logger.info("Gravity off.")
        g = agx.Vec3(0, 0, 0)  # remove gravity
        sim.setUniformGravity(g)

    # Get current delta-t (timestep) that is used in the simulation?
    dt = sim.getTimeStep()
    logger.debug("default dt = {}".format(dt))

    # Change the timestep
    sim.setTimeStep(TIMESTEP)

    # Confirm timestep changed
    dt = sim.getTimeStep()
    logger.debug("new dt = {}".format(dt))

    # Create a new empty Assembly
    scene = agxSDK.Assembly()
    scene.setName(assembly_name + "assembly")

    # Add start assembly to simulation
    sim.add(scene)

    # Create a ground plane for reference and obstacle
    if not goal:
        ground = create_body(name="ground",
                             shape=agxCollide.Box(LENGTH, LENGTH,
                                                  GROUND_WIDTH),
                             position=agx.Vec3(
                                 0, 0,
                                 -(GROUND_WIDTH + SIZE_GRIPPER / 2 + LENGTH)),
                             motion_control=agx.RigidBody.STATIC)
        sim.add(ground)

    # Create two grippers
    gripper_left = create_body(name="gripper_left" + goal_string,
                               shape=agxCollide.Box(SIZE_GRIPPER, SIZE_GRIPPER,
                                                    SIZE_GRIPPER),
                               position=agx.Vec3(-LENGTH / 2, 0, 0),
                               motion_control=agx.RigidBody.DYNAMICS)
    scene.add(gripper_left)

    gripper_right = create_body(name="gripper_right" + goal_string,
                                shape=agxCollide.Box(SIZE_GRIPPER,
                                                     SIZE_GRIPPER,
                                                     SIZE_GRIPPER),
                                position=agx.Vec3(LENGTH / 2, 0, 0),
                                motion_control=agx.RigidBody.DYNAMICS)
    scene.add(gripper_right)

    gripper_left_body = gripper_left.getRigidBody("gripper_left" + goal_string)
    gripper_right_body = gripper_right.getRigidBody("gripper_right" +
                                                    goal_string)

    # Create material
    material_cylinder = agx.Material("cylinder_material")
    bulk_material_cylinder = material_cylinder.getBulkMaterial()
    bulk_material_cylinder.setPoissonsRatio(POISSON_RATIO)
    bulk_material_cylinder.setYoungsModulus(YOUNG_MODULUS)

    cylinder = create_body(name="obstacle" + goal_string,
                           shape=agxCollide.Cylinder(CYLINDER_RADIUS,
                                                     CYLINDER_LENGTH),
                           position=agx.Vec3(0, 0, -2 * CYLINDER_RADIUS),
                           motion_control=agx.RigidBody.STATIC,
                           material=material_cylinder)
    scene.add(cylinder)

    # Create cable
    cable = agxCable.Cable(RADIUS, RESOLUTION)

    # Create Frames for each gripper:
    # Cables are attached passing through the attachment point along the Z axis of the body's coordinate frame.
    # The translation specified in the transformation is relative to the body and not the world
    left_transform = agx.AffineMatrix4x4()
    left_transform.setTranslate(SIZE_GRIPPER + RADIUS, 0, 0)
    left_transform.setRotate(
        agx.Vec3.Z_AXIS(),
        agx.Vec3.Y_AXIS())  # Rotation matrix which switches Z with Y
    frame_left = agx.Frame(left_transform)

    right_transform = agx.AffineMatrix4x4()
    right_transform.setTranslate(-SIZE_GRIPPER - RADIUS, 0, 0)
    right_transform.setRotate(
        agx.Vec3.Z_AXIS(),
        -agx.Vec3.Y_AXIS())  # Rotation matrix which switches Z with -Y
    frame_right = agx.Frame(right_transform)

    cable.add(
        agxCable.FreeNode(agx.Vec3(-LENGTH / 2 + SIZE_GRIPPER + RADIUS, 0,
                                   0)))  # Fix cable to gripper_left
    cable.add(
        agxCable.FreeNode(agx.Vec3(LENGTH / 2 - SIZE_GRIPPER - RADIUS, 0,
                                   0)))  # Fix cable to gripper_right

    # Set cable name and properties
    cable.setName("DLO" + goal_string)
    properties = cable.getCableProperties()
    properties.setYoungsModulus(YOUNG_MODULUS, agxCable.BEND)
    properties.setYoungsModulus(YOUNG_MODULUS, agxCable.TWIST)
    properties.setYoungsModulus(YOUNG_MODULUS, agxCable.STRETCH)

    material_wire = cable.getMaterial()
    wire_material = material_wire.getBulkMaterial()
    wire_material.setPoissonsRatio(POISSON_RATIO)
    wire_material.setYoungsModulus(YOUNG_MODULUS)
    cable.setMaterial(material_wire)

    # Add cable plasticity
    plasticity = agxCable.CablePlasticity()
    plasticity.setYieldPoint(
        YIELD_POINT,
        agxCable.BEND)  # set torque required for permanent deformation
    plasticity.setYieldPoint(
        YIELD_POINT,
        agxCable.STRETCH)  # set torque required for permanent deformation
    cable.addComponent(plasticity)  # NOTE: Stretch direction is always elastic

    # Tell MaterialManager to create and return a contact material which will be used
    # when two geometries both with this material is in contact
    contact_material = sim.getMaterialManager().getOrCreateContactMaterial(
        material_cylinder, material_wire)
    contact_material.setYoungsModulus(CONTACT_YOUNG_MODULUS)

    # Create a Friction model, which we tell the solver to solve ITERATIVELY (faster)
    fm = agx.IterativeProjectedConeFriction()
    fm.setSolveType(agx.FrictionModel.DIRECT)
    contact_material.setFrictionModel(fm)

    # Try to initialize cable
    report = cable.tryInitialize()
    if report.successful():
        logger.debug("Successful cable initialization.")
    else:
        logger.error(report.getActualError())

    # Add cable to simulation
    sim.add(cable)

    # Add segment names and get first and last segment
    segment_count = 0
    iterator = cable.begin()
    segment_left = iterator.getRigidBody()
    segment_left.setName('dlo_' + str(segment_count + 1) + goal_string)
    segment_right = None

    while not iterator.isEnd():
        segment_count += 1
        segment_right = iterator.getRigidBody()
        segment_right.setName('dlo_' + str(segment_count + 1) + goal_string)
        iterator.inc()

    # Add hinge constraints
    hinge_joint_left = agx.Hinge(
        sim.getRigidBody("gripper_left" + goal_string), frame_left,
        segment_left)
    hinge_joint_left.setName('hinge_joint_left' + goal_string)
    motor_left = hinge_joint_left.getMotor1D()
    motor_left.setEnable(False)
    motor_left_param = motor_left.getRegularizationParameters()
    motor_left_param.setCompliance(1e12)
    motor_left.setLockedAtZeroSpeed(False)
    lock_left = hinge_joint_left.getLock1D()
    lock_left.setEnable(False)
    range_left = hinge_joint_left.getRange1D()
    range_left.setEnable(True)
    range_left.setRange(agx.RangeReal(-math.pi / 2, math.pi / 2))
    sim.add(hinge_joint_left)

    hinge_joint_right = agx.Hinge(
        sim.getRigidBody("gripper_right" + goal_string), frame_right,
        segment_right)
    hinge_joint_right.setName('hinge_joint_right' + goal_string)
    motor_right = hinge_joint_right.getMotor1D()
    motor_right.setEnable(False)
    motor_right_param = motor_right.getRegularizationParameters()
    motor_right_param.setCompliance(1e12)
    motor_right.setLockedAtZeroSpeed(False)
    lock_right = hinge_joint_right.getLock1D()
    lock_right.setEnable(False)
    range_right = hinge_joint_right.getRange1D()
    range_right.setEnable(True)
    range_right.setRange(agx.RangeReal(-math.pi / 2, math.pi / 2))
    sim.add(hinge_joint_right)

    # Create bases for gripper motors
    prismatic_base_left = create_locked_prismatic_base(
        "gripper_left" + goal_string,
        gripper_left_body,
        compliance=0,
        motor_ranges=[(-FORCE_RANGE, FORCE_RANGE), (-FORCE_RANGE, FORCE_RANGE),
                      (-FORCE_RANGE, FORCE_RANGE)],
        position_ranges=[(-LENGTH / 2 + CYLINDER_RADIUS,
                          LENGTH / 2 - CYLINDER_RADIUS),
                         (-CYLINDER_LENGTH / 3, CYLINDER_LENGTH / 3),
                         (-(GROUND_WIDTH + SIZE_GRIPPER / 2 + LENGTH), 0)],
        lock_status=[False, False, False])
    sim.add(prismatic_base_left)
    prismatic_base_right = create_locked_prismatic_base(
        "gripper_right" + goal_string,
        gripper_right_body,
        compliance=0,
        motor_ranges=[(-FORCE_RANGE, FORCE_RANGE), (-FORCE_RANGE, FORCE_RANGE),
                      (-FORCE_RANGE, FORCE_RANGE)],
        position_ranges=[(-LENGTH / 2 + CYLINDER_RADIUS,
                          LENGTH / 2 - CYLINDER_RADIUS),
                         (-CYLINDER_LENGTH / 3, CYLINDER_LENGTH / 3),
                         (-(GROUND_WIDTH + SIZE_GRIPPER / 2 + LENGTH), 0)],
        lock_status=[False, False, False])
    sim.add(prismatic_base_right)

    return sim
Beispiel #9
0
def buildBot(sim, root, bot_pos, controller='Arrows', drivetrain = 'FWD', color=False):
    body_wid = 0.32
    body_len = 0.6
    body_hei = 0.16 
    
    wheel_rad = 0.07
    wheel_wid = 0.02
    wheel_dmp = -0.02

    body = agx.RigidBody( agxCollide.Geometry( agxCollide.Box(body_wid/2, body_len/2, body_hei/2)))
    body.setPosition(bot_pos[0], bot_pos[1], bot_pos[2] + body_hei/2 + wheel_rad + wheel_dmp )
    # body.setMotionControl(1)
    body.setRotation(agx.Quat(np.pi, agx.Vec3(0,0,1)))
    sim.add(body)
    vis_body = agxOSG.createVisual(body, root)
    if color:
        agxOSG.setDiffuseColor(vis_body, color)
    else:
        agxOSG.setTexture(vis_body, 'flames.png', True, agxOSG.DIFFUSE_TEXTURE, 1.0, 1.0)

    wheelLF = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(wheel_rad, wheel_wid)))
    wheelLF.setPosition(bot_pos[0]-(body_wid/2+wheel_wid/2), bot_pos[1]+(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad)
    # wheelLF.setMotionControl(1)
    wheelLF.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(wheelLF)
    # agxOSG.setDiffuseColor(agxOSG.createVisual(wheelLF, root), agxRender.Color.Red())

    wheelRF = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(wheel_rad, wheel_wid)))
    wheelRF.setPosition(bot_pos[0]+(body_wid/2+wheel_wid/2), bot_pos[1]+(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad)
    # wheelRF.setMotionControl(1)
    wheelRF.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(wheelRF)
    # agxOSG.setDiffuseColor(agxOSG.createVisual(wheelRF, root), agxRender.Color.Red())

    wheelLB = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(wheel_rad, wheel_wid)))
    wheelLB.setPosition(bot_pos[0]-(body_wid/2+wheel_wid/2), bot_pos[1]-(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad)
    # wheelLB.setMotionControl(1)
    wheelLB.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(wheelLB)
    # agxOSG.setDiffuseColor(agxOSG.createVisual(wheelLB, root), agxRender.Color.Red())

    wheelRB = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(wheel_rad, wheel_wid)))
    wheelRB.setPosition(bot_pos[0]+(body_wid/2+wheel_wid/2), bot_pos[1]-(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad)
    # wheelRB.setMotionControl(1)
    wheelRB.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(wheelRB)
    # agxOSG.setDiffuseColor(agxOSG.createVisual(wheelRB, root), agxRender.Color.Red())

    for wheel in [wheelLB, wheelLF, wheelRB, wheelRF]:
        vis_body = agxOSG.createVisual(wheel, root)
        agxOSG.setTexture(vis_body, 'tire.png', True, agxOSG.DIFFUSE_TEXTURE, 1.0, 1.0)

    light_rad = 0.02
    light_dep = 0.01

    headlightL = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(light_rad, light_dep)))
    headlightL.setPosition( bot_pos[0] + 0.79*body_wid/2, bot_pos[1] + body_len/2+light_dep/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp)
    # headlightL.setMotionControl(1)
    # headlightL.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(headlightL)
    agxOSG.setTexture(agxOSG.createVisual(headlightL, root), 'light.png', True, agxOSG.DIFFUSE_TEXTURE, 1.0, 1.0)
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3( bot_pos[0] + 0.79*body_wid/2, bot_pos[1] + body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp ))
    HLL = agx.Hinge(hf, body, headlightL)
    sim.add(HLL)

    headlightR = agx.RigidBody(agxCollide.Geometry( agxCollide.Cylinder(light_rad, light_dep)))
    headlightR.setPosition(bot_pos[0] -0.79*body_wid/2, bot_pos[1] + body_len/2+light_dep/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp )
    # headlightR.setMotionControl(1)
    # headlightL.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(headlightR)
    agxOSG.setTexture(agxOSG.createVisual(headlightR, root), 'light.png', True, agxOSG.DIFFUSE_TEXTURE, 1.0, 1.0)
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3(bot_pos[0] -0.79*body_wid/2, bot_pos[1] + body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp ))
    HLR = agx.Hinge(hf, body, headlightR)
    sim.add(HLR)


    light_wid = 0.012
    light_hei = 0.02
    light_dep = 0.003

    taillightL = agx.RigidBody(agxCollide.Geometry( agxCollide.Box(light_wid, light_dep, light_hei)))
    taillightL.setPosition(bot_pos[0] -0.79*body_wid/2,bot_pos[1] -(body_len/2+light_dep/2), bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp)
    # taillightL.setMotionControl(1)
    # headlightL.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(taillightL)
    agxOSG.setDiffuseColor(agxOSG.createVisual(taillightL, root), agxRender.Color.Red())
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3(bot_pos[0] -0.79*body_wid/2, bot_pos[1] -body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp + light_hei/3))
    TLL_hi = agx.Hinge(hf, body, taillightL)
    sim.add(TLL_hi)
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3(bot_pos[0] -0.79*body_wid/2, bot_pos[1] -body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp - light_hei/3))
    TLL_low = agx.Hinge(hf, body, taillightL)
    sim.add(TLL_low)

    taillightR = agx.RigidBody(agxCollide.Geometry( agxCollide.Box(light_wid, light_dep, light_hei)))
    taillightR.setPosition( bot_pos[0] + 0.79*body_wid/2,bot_pos[1] -(body_len/2+light_dep/2), bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp)
    # taillightR.setMotionControl(1)
    # headlightL.setRotation(agx.Quat(np.pi/2, agx.Vec3(0,0,1)))
    sim.add(taillightR)
    agxOSG.setDiffuseColor(agxOSG.createVisual(taillightR, root), agxRender.Color.Red())
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3( bot_pos[0] + 0.79*body_wid/2,bot_pos[1]-body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp + light_hei/3))
    TLR = agx.Hinge(hf, body, taillightR)
    sim.add(TLR)
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,1,0))
    hf.setCenter(agx.Vec3( bot_pos[0] + 0.79*body_wid/2,bot_pos[1]-body_len/2, bot_pos[2] + 0.7*body_hei + wheel_rad + wheel_dmp - light_hei/3))
    TLR = agx.Hinge(hf, body, taillightR)
    sim.add(TLR)

    windangle = np.pi/4
    windshield = agx.RigidBody( agxCollide.Geometry( agxCollide.Box(0.9*body_wid/2, 0.005, body_hei/3)))
    windshield.setPosition(bot_pos[0], bot_pos[1]+body_len/5, bot_pos[2] + body_hei + wheel_rad + wheel_dmp + np.cos(windangle)*body_hei/3)
    # windshield.setTorque(0,0,100)
    # windshield.setMotionControl(2)
    windshield.setRotation(agx.Quat(windangle, agx.Vec3(1,0,0)))
    sim.add(windshield)
    agxOSG.setTexture(agxOSG.createVisual(windshield, root), 'windshield.jpg', True, agxOSG.DIFFUSE_TEXTURE, 1.0, 1.0)


    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,0,1))
    hf.setCenter(agx.Vec3(-body_wid/3, body_len/5, bot_pos[2] + body_hei + wheel_rad + wheel_dmp))
    windh1 = agx.Hinge(hf, body, windshield)
    sim.add(windh1)
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(0,0,1))
    hf.setCenter(agx.Vec3(body_wid/3, body_len/5, bot_pos[2] + body_hei + wheel_rad + wheel_dmp))
    windh2 = agx.Hinge(hf, body, windshield)
    sim.add(windh2)

    

    
    x_ax = agx.Vec3(1,0,0)
    y_ax = agx.Vec3(0,1,0)
    z_ax = agx.Vec3(0,0,1)

    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(-1,0,0))
    hf.setCenter(agx.Vec3(bot_pos[0]-body_wid/2, bot_pos[1]+(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad))
    axleLF = agx.Hinge(hf, body, wheelLF)
    sim.add(axleLF)

    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(-1,0,0))
    hf.setCenter(agx.Vec3(bot_pos[0]-body_wid/2, bot_pos[1]-(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad))
    axleLB = agx.Hinge(hf, body, wheelLB)
    sim.add(axleLB)

    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3( 1,0,0))
    hf.setCenter(agx.Vec3(bot_pos[0]+body_wid/2, bot_pos[1]-(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad))
    axleRB = agx.Hinge(hf, body, wheelRB)
    sim.add(axleRB)
    
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3( 1,0,0))
    hf.setCenter(agx.Vec3(bot_pos[0]+body_wid/2, bot_pos[1]+(body_len/2-wheel_rad*1.8), bot_pos[2]+wheel_rad))
    axleRF = agx.Hinge(hf, body, wheelRF)
    sim.add(axleRF)

    wheels = [wheelLF, wheelRF] # default FWD
    if drivetrain == 'FWD':
        wheels = [wheelLF, wheelRF]
    elif drivetrain == 'RWD':
        wheels = [wheelLB, wheelRB]
    elif drivetrain == 'AWD':
        wheels = [wheelLF, wheelRF, wheelLB, wheelRB]
    
    if controller == 'Numpad':
        sim.add(WheelControllerNumpad(wheels))
        sim.add(Fjoink(body).setHopper(agxSDK.GuiEventListener.KEY_KP_Subtract))
    else:
        sim.add(WheelControllerArrows(wheels))
        sim.add(Fjoink(body))

    # return a pointer to the body
    return body
Beispiel #10
0
def obstacles(sim, root, h):
    #start plattform
    dims = [1.5, 1.5, 0.06]
    pos = [-6, 0, h + dims[2] / 2]
    startbox = addboxx(sim, root, dims, pos)

    #timer
    timer = Timer(startbox)
    sim.add(timer)

    dims = [0.1, 1.5, 0.3]
    pos = [-6.75, 0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.1, 1.5, 0.3]
    pos = [-5.25, 0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [1.6, 0.1, 0.3]
    pos = [-6, -0.75, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    # wall

    dims = [4.0, 0.1, 0.22]
    pos = [-3.3, -0.6, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    # Random stuff in the first quarter
    dims = [0.2, 0.2, 0.8]
    pos = [-4, 0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.4, 0.25, 0.2]
    pos = [-3, 1.5, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    for i in range(30):
        x = -0.5 - random.random() * 4.75
        y = -0.5 + random.random() * 6
        dims = [
            random.random() * 0.6,
            random.random() * 0.6,
            random.random() * 0.6
        ]
        pos = agx.Vec3(x, y, 0)
        if pos.length() < 1.5:
            pos.setLength(1.5 + random.random() * 3.75)
        if pos.length() > 7.0:
            pos.setLength(1.5 + random.random() * 5.5)
        pos.set(h + dims[2] / 2, 2)
        addboxx(sim, root, dims, pos)

    # Pole in the middle with walls around
    dims = [0.28, 1.4]
    pos = [0, 0, h + dims[1] / 2]
    can = addcylinder(sim, root, dims, pos, texture='schrodbull.png')
    can.setRotation(agx.Quat(np.pi / 2, agx.Vec3(1, 0, 0)))
    pos = [0, 0, h + dims[1]]
    dims = [0.28, 0.025]
    pos[2] = pos[2] + dims[1] / 2
    lid = addcylinder(sim, root, dims, pos, texture='sodacan_lid.png')
    lid.setRotation(agx.Quat(np.pi / 2, agx.Vec3(1, 0, 0)))

    dims = [0.3, 2.0, 0.4]
    pos = [-1.15, 0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [2.6, 0.3, 0.4]
    pos = [0, -1.15, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.3, 2.0, 0.4]
    pos = [1.15, 0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.3, 7.0, 0.4]
    pos = [0, 3.5, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    # Seesaw board
    dims = [2.1, 0.25, 0.3]
    pos = [2.1, 0.4, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)
    seesaw(sim, root, [3.75, 0.9, h], -0.85 * np.pi, h=0.1)
    dims = [0.5, 3.8, 0.18]
    pos = [4.8, 3.15, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    # Ballroom walls
    dims = [0.25, 4.3, 0.3]
    pos = [6.0, 0.0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.25, 1.0, 0.3]
    pos = [2.1, -1.0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.25, 1.4, 0.3]
    pos = [3.0, -0.4, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.25, 2.4, 0.3]
    pos = [2.5, -3.0, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [1.1, 0.25, 0.3]
    pos = [3.1, -3.1, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [0.66, 0.25, 0.3]
    pos = [2.3, -1.65, h + dims[2] / 2]
    wall_1 = addboxx(sim, root, dims, pos)
    dims = [2.8, 0.25, 0.3]
    pos = [3.95, -2.0, h + dims[2] / 2]
    wall_2 = addboxx(sim, root, dims, pos)
    dims = [3.91, 0.25, 0.3]
    pos = [4.65, -3.45, h + dims[2] / 2]
    wall_3 = addboxx(sim, root, dims, pos)
    wall_1.setRotation(agx.Quat(-np.pi / 4, agx.Vec3(0, 0, 1)))
    wall_2.setRotation(agx.Quat(-np.pi / 4, agx.Vec3(0, 0, 1)))
    wall_3.setRotation(agx.Quat(np.pi / 4, agx.Vec3(0, 0, 1)))

    # Ballroom balls
    for i in range(200):
        x = 4.0 + random.random() * 2.8
        y = 0.75 - random.random() * 2.5
        rad = 0.025 + random.random() * 0.075
        pos = agx.Vec3(x, y, h + rad + 3 * random.random() * rad)
        addball(sim, root, rad, pos, Fixed=False)

    # Climbing ramp
    dx = 0.8
    bot_tilt = 0.0445
    dims = [dx, 2.5, 0.6]
    bot_tilt = np.arcsin(0.45 / (2.5 * 4))
    dif = dims[1] / 2 * np.cos(bot_tilt) - 0.002 * np.sin(bot_tilt)
    dh = 2 * np.sin(bot_tilt) * dif
    for i in range(4):
        angle = (i + 1) * np.pi
        pos = [2 - dx * i, -4.7 - 0.015 * (-1)**i, -0.3 + h + (i + 1 / 2) * dh]
        hip = addboxx(sim, root, dims, pos)
        hip.setRotation(agx.Quat(bot_tilt, agx.Vec3(1, 0, 0)))
        hip.setRotation(hip.getRotation() * agx.Quat(angle, agx.Vec3(0, 0, 1)))
        addboxx(sim, root, [2 * dx, 1.1, dims[2]], [
            2 - dx * (i + 1 / 2), -4.7 - 1.8 * ((-1)**i), -0.3 + h +
            (i + 1) * dh
        ])

    # Bridge boxes
    dims = [1.5, 1.8, 0.45]
    pos = [-1.5, -3.25, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    dims = [1.5, 1.8, 0.45]
    pos = [-4.5, -3.25, h + dims[2] / 2]
    addboxx(sim, root, dims, pos)

    # Bridge part
    bridge = addboxx(sim, root, [1.5, 0.5, 0.08],
                     [-3.0, -3.25, h + 0.45 - 0.04])
    timer.addCheckpoint(bridge)

    # Swinging ball over bridge
    rad = 0.4
    pendulum = addball(sim,
                       root,
                       rad, [-3.0, -3.25, h + 0.45 + rad + 0.01],
                       Fixed=False)
    pendulum.setVelocity(agx.Vec3(0, 5, 0))
    hf = agx.HingeFrame()
    hf.setAxis(agx.Vec3(1, 0, 0))
    hf.setCenter(agx.Vec3(-3.0, -3.25, 3.0 + h + 0.45 + rad + 0.01))
    axleP = agx.Hinge(hf, pendulum)
    sim.add(axleP)
    # addboxx(sim, root, [1.5, 0.5, 0.08], )

    # final ramp
    addboxx(sim, root, [0.1, 2.5, 0.5], [-6.5, -2.05, h + 0.5 / 2])
    addboxx(sim, root, [0.1, 2.5, 0.5], [-5.5, -2.05, h + 0.5 / 2])

    hip = addboxx(sim, root, [0.9, 1.5, 0.1],
                  [-6.0, -1.53, h + 0.026 + np.sin(0.15) * 1.5 / 2])
    hip.setRotation(agx.Quat(0.15, agx.Vec3(1, 0, 0)))

    addboxx(sim, root, [0.9, 2.0, 0.2], [-6.0, -2.25, h + 0.075])
    addboxx(sim, root, [1.4, 0.8, 0.2], [-5.8, -3.7, h + 0.45 - 0.1])

    hip = addboxx(sim, root, [0.9, 1.5, 0.1],
                  [-6.0, -3.0, h + 0.026 + np.sin(0.15) * 1.5 / 2])
    hip.setRotation(agx.Quat(-0.15, agx.Vec3(1, 0, 0)))
Beispiel #11
0
def build_simulation():
    # Instantiate a simulation
    sim = agxSDK.Simulation()

    # By default the gravity vector is 0,0,-9.81 with a uniform gravity field. (we CAN change that
    # too by creating an agx.PointGravityField for example).
    # AGX uses a right-hand coordinate system (That is Z defines UP. X is right, and Y is into the screen)
    if not GRAVITY:
        logger.info("Gravity off.")
        g = agx.Vec3(0, 0, 0)  # remove gravity
        sim.setUniformGravity(g)

    # Get current delta-t (timestep) that is used in the simulation?
    dt = sim.getTimeStep()
    logger.debug("default dt = {}".format(dt))

    # Change the timestep
    sim.setTimeStep(TIMESTEP)

    # Confirm timestep changed
    dt = sim.getTimeStep()
    logger.debug("new dt = {}".format(dt))

    # Define materials
    material_hard = agx.Material("Aluminum")
    material_hard_bulk = material_hard.getBulkMaterial()
    material_hard_bulk.setPoissonsRatio(ALUMINUM_POISSON_RATIO)
    material_hard_bulk.setYoungsModulus(ALUMINUM_YOUNG_MODULUS)

    # Create box with pocket
    side_length = 0.15
    thickness_outer_wall = 0.01
    body = create_body(name="ground", shape=agxCollide.Box(side_length, side_length, 0.01),
                       position=agx.Vec3(0, 0, -0.005),
                       motion_control=agx.RigidBody.STATIC,
                       material=material_hard)

    sim.add(body)

    body = create_body(name="walls", shape=agxCollide.Box(thickness_outer_wall, side_length, 0.04),
                       position=agx.Vec3(side_length + thickness_outer_wall, 0, 0.0),
                       motion_control=agx.RigidBody.STATIC,
                       material=material_hard)
    sim.add(body)

    body = create_body(name="walls", shape=agxCollide.Box(thickness_outer_wall, side_length, 0.04),
                       position=agx.Vec3(-(side_length + thickness_outer_wall), 0, 0.0),
                       motion_control=agx.RigidBody.STATIC,
                       material=material_hard)
    sim.add(body)

    body = create_body(name="walls",
                       shape=agxCollide.Box(side_length + 2 * thickness_outer_wall, thickness_outer_wall, 0.04),
                       position=agx.Vec3(0, -(side_length + thickness_outer_wall), 0.0),
                       motion_control=agx.RigidBody.STATIC,
                       material=material_hard)
    sim.add(body)

    body = create_body(name="walls",
                       shape=agxCollide.Box(side_length + 2 * thickness_outer_wall, thickness_outer_wall, 0.04),
                       position=agx.Vec3(0, side_length + thickness_outer_wall, 0.0),
                       motion_control=agx.RigidBody.STATIC,
                       material=material_hard)
    sim.add(body)

    # Create gripper 0
    gripper_0 = create_body(name="gripper_0",
                            shape=agxCollide.Sphere(0.005),
                            position=agx.Vec3(-(LENGTH/2), OFFSET_Y, 0.0025),
                            motion_control=agx.RigidBody.DYNAMICS,
                            material=material_hard)
    gripper_0.getRigidBody("gripper_0").getGeometry("gripper_0").setEnableCollisions(False)
    sim.add(gripper_0)

    # Create base for gripper motors
    prismatic_base_0 = create_locked_prismatic_base("gripper_0", gripper_0.getRigidBody("gripper_0"),
                                                    position_ranges=[(-side_length*2, side_length*2),
                                                                     (-side_length*2, side_length*2),
                                                                     (-0.1, 0.01)],
                                                    motor_ranges=[(-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE),
                                                                  (-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE),
                                                                  (-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE)],
                                                    lock_status=[False, False, False])

    sim.add(prismatic_base_0)

    # Create gripper
    gripper_1 = create_body(name="gripper_1",
                            shape=agxCollide.Sphere(0.005),
                            position=agx.Vec3((LENGTH/2), OFFSET_Y, 0.0025),
                            motion_control=agx.RigidBody.DYNAMICS,
                            material=material_hard)
    gripper_1.getRigidBody("gripper_1").getGeometry("gripper_1").setEnableCollisions(False)
    sim.add(gripper_1)

    # Create base for gripper motors
    prismatic_base_0 = create_locked_prismatic_base("gripper_1", gripper_1.getRigidBody("gripper_1"),
                                                    position_ranges=[(-side_length*2, side_length*2),
                                                                     (-side_length*2, side_length*2),
                                                                     (-0.1, 0.01)],
                                                    motor_ranges=[(-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE),
                                                                  (-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE),
                                                                  (-MAX_MOTOR_FORCE, MAX_MOTOR_FORCE)],
                                                    lock_status=[False, False, False])
    sim.add(prismatic_base_0)
    
    # Create goal obstacle
    goal_obstacle = create_body(name="obstacle_goal",
                           shape=agxCollide.Cylinder(2 * R_GOAL_OBSTACLE, 0.1),
                           position=agx.Vec3(0.0,0.-0.075, 0.005),
                           motion_control=agx.RigidBody.STATIC,
                           material=material_hard)
    sim.add(goal_obstacle)
    rotation_cylinder = agx.OrthoMatrix3x3()
    rotation_cylinder.setRotate(agx.Vec3.Y_AXIS(), agx.Vec3.Z_AXIS())
    goal_obstacle.setRotation(rotation_cylinder)

    # Create obstacles
    obs_pos = OBSTACLE_POSITIONS
    for i in range(0, len(obs_pos)):
        obstacle = create_body(name="obstacle",
                               shape=agxCollide.Box(0.01, 0.015, 0.05),
                               position=agx.Vec3(obs_pos[i][0], obs_pos[i][1], 0.005),
                               motion_control=agx.RigidBody.STATIC,
                               material=material_hard)
        sim.add(obstacle)

    # Create rope and set name + properties
    dlo = agxCable.Cable(RADIUS, RESOLUTION)
    dlo.setName("DLO")
    material_rubber_band= dlo.getMaterial()
    rubber_band_material = material_rubber_band.getBulkMaterial()
    rubber_band_material.setPoissonsRatio(PEG_POISSON_RATIO)
    properties = dlo.getCableProperties()
    properties.setYoungsModulus(YOUNG_MODULUS_BEND, agxCable.BEND)
    properties.setYoungsModulus(YOUNG_MODULUS_TWIST, agxCable.TWIST)
    properties.setYoungsModulus(YOUNG_MODULUS_STRETCH, agxCable.STRETCH)

    dlo.add(agxCable.FreeNode(gripper_0.getRigidBody("gripper_0").getPosition()))
    dlo.add(agxCable.FreeNode(gripper_1.getRigidBody("gripper_1").getPosition()))
    #
    # hf = agx.HingeFrame()
    # hf.setCenter(gripper_0.getRigidBody("gripper_0").getPosition())
    # hf.setAxis(agx.Vec3(0,1,0))
    # hinge_0 = agx.Hinge(hf, base_z, rot_y)
    # agx.Hinge()


    # dlo.add(agxCable.BodyFixedNode(gripper_0.getRigidBody("gripper_0"), agx.Vec3()))
    # dlo.add(agxCable.BodyFixedNode(gripper_1.getRigidBody("gripper_1"),  agx.Vec3()))

    # Set angular damping for segments
    sim.add(dlo)
    segment_iterator = dlo.begin()
    n_segments = dlo.getNumSegments()
    segments = []
    for i in range(n_segments):
        if not segment_iterator.isEnd():
            seg = segment_iterator.getRigidBody()
            segments.append(seg)
            seg.setAngularVelocityDamping(2e4)
            segment_iterator.inc()
            mass_props = seg.getMassProperties()
            mass_props.setMass(1.25*mass_props.getMass())


    s0 = segments[0]
    s1 = segments[-1]

    h0 = agx.HingeFrame()
    h0.setCenter(gripper_0.getRigidBody("gripper_0").getPosition())
    h0.setAxis(agx.Vec3(0,0,1))
    l0 = agx.Hinge(h0, s0, gripper_0.getRigidBody("gripper_0") )
    sim.add(l0)

    h1 = agx.HingeFrame()
    h1.setCenter(gripper_1.getRigidBody("gripper_1").getPosition())
    h1.setAxis(agx.Vec3(0,0,1))
    l1 = agx.Hinge(h1, s1, gripper_1.getRigidBody("gripper_1") )
    sim.add(l1)

    # f0 = agx.Frame()
    # f1 = agx.Frame()
    # l0 = agx.LockJoint(s0, f0, gripper_0.getRigidBody("gripper_0"), f1)
    # l1 = agx.LockJoint(s1, f0, gripper_1.getRigidBody("gripper_1"), f1)
    # sim.add(l0)
    # sim.add(l1)

    # Try to initialize dlo
    report = dlo.tryInitialize()
    if report.successful():
        print("Successful dlo initialization.")
    else:
        print(report.getActualError())

    # Add rope to simulation
    sim.add(dlo)

    # Set rope material
    material_rubber_band = dlo.getMaterial()
    material_rubber_band.setName("rope_material")

    contactMaterial = sim.getMaterialManager().getOrCreateContactMaterial(material_hard, material_rubber_band)
    contactMaterial.setYoungsModulus(1e12)
    fm = agx.IterativeProjectedConeFriction()
    fm.setSolveType(agx.FrictionModel.DIRECT)
    contactMaterial.setFrictionModel(fm)

    # Add keyboard listener
    motor_x_0 = sim.getConstraint1DOF("gripper_0_joint_base_x").getMotor1D()
    motor_y_0 = sim.getConstraint1DOF("gripper_0_joint_base_y").getMotor1D()
    motor_x_1 = sim.getConstraint1DOF("gripper_1_joint_base_x").getMotor1D()
    motor_y_1 = sim.getConstraint1DOF("gripper_1_joint_base_y").getMotor1D()
    key_motor_map = {agxSDK.GuiEventListener.KEY_Up: (motor_y_0, 0.5),
                     agxSDK.GuiEventListener.KEY_Down: (motor_y_0, -0.5),
                     agxSDK.GuiEventListener.KEY_Right: (motor_x_0, 0.5),
                     agxSDK.GuiEventListener.KEY_Left: (motor_x_0, -0.5),
                     120: (motor_x_1, 0.5),
                     60: (motor_x_1, -0.5),
                     97: (motor_y_1, 0.5),
                     121: (motor_y_1, -0.5)}
    sim.add(KeyboardMotorHandler(key_motor_map))

    rbs = dlo.getRigidBodies()
    for i in range(len(rbs)):
        rbs[i].setName('dlo_' + str(i+1))

    return sim