def test_BasicShapes(self): """ Create the basic shapes and verify their names. Furthermore, verify that scaling them works. """ # Create the Collision Shape instances. cs_p = StaticPlaneShape(Vec3(0, 1, 2), 3) cs_s = SphereShape(3) cs_b = BoxShape(Vec3(1, 2, 3)) cs_e = EmptyShape() # Verify the dimensions of the sphere and the box. assert cs_s.getRadius() == 3 assert cs_b.getHalfExtentsWithMargin() == Vec3(1, 2, 3) # Put the collision shapes into a dictionary where the key is the # expected name. shapes = {b"STATICPLANE": cs_p, b"SPHERE": cs_s, b"Box": cs_b, b"Empty": cs_e} # Verify the name of each shape and modify its scale. scale = Vec3(1.5, 2.5, 3.5) for name, cs in shapes.items(): cs.setLocalScaling(scale) assert cs.getLocalScaling() == scale assert cs.getName() == name
def test_calculateLocalInertia(self): """ Create a sphere and let Bullet compute its inertia via the 'calculateLocalInertia' method. Verify that the result is correct. """ # Compute the inertia of the sphere. The inertia for a sphere is # I = 2 / 5 * mass * (R ** 2) mass, radius = 2, 3 sphere = SphereShape(radius) inertia = sphere.calculateLocalInertia(mass) ref = 2 / 5 * mass * radius ** 2 assert np.allclose(inertia.topy(), ref * np.ones(3))
def runSimulation(sim): # Create the collision shapes for the ball and ground. cs_ball = SphereShape(1) cs_ground = StaticPlaneShape(Vec3(0, 1, 0), 1) # Create a Rigid Body for the static (ie mass=0) Ground. q0 = Quaternion(0, 0, 0, 1) ms = DefaultMotionState(Transform(q0, Vec3(0, -1, 0))) ci = RigidBodyConstructionInfo(0, ms, cs_ground) rb_ground = RigidBody(ci, bodyID=1) del ms, ci # Create a Rigid body for the dynamic (ie mass > 0) Ball. ms = DefaultMotionState(Transform(q0, Vec3(0, 5, 0))) inertia = cs_ball.calculateLocalInertia(1) ci = RigidBodyConstructionInfo(1, ms, cs_ball, inertia) rb_ball = RigidBody(ci, bodyID=2) del ms, inertia, ci # Ensure that Bullet never deactivates the objects. rb_ground.forceActivationState(4) rb_ball.forceActivationState(4) # Add both bodies to the simulation. sim.addRigidBody(rb_ground) sim.addRigidBody(rb_ball) # Sanity check: the ball must be at position y=5 pos = rb_ball.getMotionState().getWorldTransform().getOrigin() pos = pos.topy() assert pos[1] == 5 # Step the simulation long enough for the ball to fall down and # come to rest on the plane. for ii in range(10): sim.stepSimulation(1, 100) # Verify that the y-position of the ball is such that the ball # rests on the plane. pos = rb_ball.getMotionState().getWorldTransform().getOrigin() return pos.topy()
def getRB(pos=Vec3(0, 0, 0), cshape=SphereShape(1)): """ Return a Rigid Body plus auxiliary information (do *not* delete; see note below). .. note:: Do not delete the tuple until the end of the test because it may lead to memory access violations. The reason is that a rigid body requires several indepenent structures that need to remain in memory. """ t = Transform(Quaternion(0, 0, 0, 1), pos) ms = DefaultMotionState(t) mass = 1 # Build construction info and instantiate the rigid body. ci = RigidBodyConstructionInfo(mass, ms, cshape) return RigidBody(ci)
""" Python version of Bullet's own 'Hello World' demo using 'azBullet' wrapper. """ import azBullet from azBullet import Vec3, Quaternion from azBullet import StaticPlaneShape, SphereShape from azBullet import DefaultMotionState, Transform from azBullet import RigidBody, RigidBodyConstructionInfo sim = azBullet.BulletBase() sim.setGravity(Vec3(0, -10, 0)) # Create a collision shape for the Ball and for the Ground. ballShape = SphereShape(1) groundShape = StaticPlaneShape(Vec3(0, 1, 0), 1) # Create a Rigid Body for the Ground based on the collision shape. mass = 0 groundRigidBodyState = DefaultMotionState( Transform(Quaternion(0, 0, 0, 1), Vec3(0, -1, 0))) ci = RigidBodyConstructionInfo(mass, groundRigidBodyState, groundShape) groundRigidBody = RigidBody(ci) groundRigidBody.setRestitution(1.0) sim.addRigidBody(groundRigidBody) del mass, ci # Create a Rigid body for the Ball based on its collision shape. Let Bullet do # the heavy lifting and compute the mass and inertia for us. fallRigidBodyState = DefaultMotionState( Transform(Quaternion(0, 0, 0, 1), Vec3(0, 20, 0))) mass = 1
def main(): # Create two rigid bodies side by side (they *do* touch, but just). pos_a = Vec3(-10, 0, 0) pos_b = Vec3(10, 0, 0) r = 0.001 rb_a = getRB(pos=pos_a, cshape=SphereShape(r)) rb_b = getRB(pos=pos_b, cshape=SphereShape(r)) del r # Create the constraint between the two bodies. The constraint applies # at (0, 0, 0) in world coordinates. frameInA = Transform(Quaternion(0, 1, 0, 0), Vec3(5, 0, 0)) frameInB = Transform(Quaternion(0, -1, 0, 0), Vec3(-5, 0, 0)) frameInA.setIdentity() frameInB.setIdentity() clsDof6 = Generic6DofSpring2Constraint dof = clsDof6(rb_a, rb_b, frameInA, frameInB) # We are now emulating a slider constraint with this 6DOF constraint. # For this purpose we need to specify the linear/angular limits. sliderLimitLo = -100 sliderLimitHi = 100 # Apply the linear/angular limits. dof.setLinearLowerLimit(Vec3(sliderLimitLo, sliderLimitLo, sliderLimitLo)) dof.setLinearLowerLimit(Vec3(sliderLimitHi, sliderLimitHi, sliderLimitHi)) tmp = 0 * np.pi / 12 dof.setAngularLowerLimit(Vec3(-tmp, -tmp, -tmp)) dof.setAngularUpperLimit(Vec3(tmp, tmp, tmp)) # Activate the spring for all three translational axis and disable it # for the three angular axis. for ii in range(3): dof.enableSpring(ii, True) dof.enableSpring(3 + ii, False) dof.setStiffness(ii, 0.1) dof.setDamping(ii, 1) dof.setEquilibriumPoint(ii, 0) # Add both rigid bodies and the constraint to the Bullet simulation. bb = azBullet.BulletBase() bb.setGravity(Vec3(0, 0, 0)) bb.addRigidBody(rb_a) bb.addRigidBody(rb_b) rb_a.forceActivationState(4) rb_b.forceActivationState(4) bb.addConstraint(dof) # Pull the right object to the right. Initially this must not affect # the object on the left until the slider is fully extended, at which # point the left object must begin to move as well. # rb_a.applyCentralForce(Vec3(0, -1, 0)) # rb_b.applyCentralForce(Vec3(0, 1, 0)) numIter = 1000 out_a = np.zeros((numIter, 3)) out_b = np.zeros_like(out_a) for ii in range(numIter): if ii == 1: rb_a.applyCentralForce(Vec3(0, 0, 0)) rb_b.applyCentralForce(Vec3(0, 0, 0)) # Step simulation. bb.stepSimulation(1 / 60, 60) # Query the position of the objects. p_a = rb_a.getCenterOfMassTransform().getOrigin().topy() p_b = rb_b.getCenterOfMassTransform().getOrigin().topy() out_a[ii, :] = p_a out_b[ii, :] = p_b animateMotion(out_a, out_b)
Test behaviour of compound shapes in terms of their masses and inertia. """ import azBullet from azBullet import Vec3, Quaternion from azBullet import StaticPlaneShape, SphereShape, CompoundShape from azBullet import DefaultMotionState, Transform from azBullet import RigidBody, RigidBodyConstructionInfo from IPython import embed as ipshell # Instantiate the Bullet simulation. sim = azBullet.BulletBase() sim.setGravity(Vec3(0, 0, 0)) # Create the spherical collision shape and a compound shape. csSphere = SphereShape(radius=1) cs = azBullet.CompoundShape() # Specify the mass and let Bullet compute the Inertia. total_mass = 1 print('Inertia sphere: ', csSphere.calculateLocalInertia(total_mass)) # Add collision shapes to the compound. Its constituents are two spheres # at different positions. t1 = Transform(Quaternion(0, 0, 0, 1), Vec3(0, -5, 0)) t2 = Transform(Quaternion(0, 0, 0, 1), Vec3(0, 5, 0)) cs.addChildShape(t1, csSphere) cs.addChildShape(t2, csSphere) # The local inertia is only a crude approximation based on the AABBs. Do not # use it. Use calculatePrincipalAxisTransform instead (see below).
""" Python version of Bullet's own 'Hello World' demo using 'azBullet' wrapper. """ import azBullet from azBullet import Vec3, Quaternion from azBullet import StaticPlaneShape, SphereShape from azBullet import DefaultMotionState, Transform from azBullet import RigidBody, RigidBodyConstructionInfo # Instantiate the Bullet simulation. sim = azBullet.BulletBase() sim.setGravity(Vec3(0, -10, 0)) # Create the collision shape for Ball and Ground. ballShape = SphereShape(1) groundShape = StaticPlaneShape(Vec3(0, 1, 0), 1) # Create the rigid body for the Ground. Since it is a static body its mass must # be zero. mass = 0 groundRigidBodyState = DefaultMotionState( Transform(Quaternion(0, 0, 0, 1), Vec3(0, -1, 0))) ci = RigidBodyConstructionInfo(mass, groundRigidBodyState, groundShape) groundRigidBody = RigidBody(ci) groundRigidBody.setRestitution(1.0) sim.addRigidBody(groundRigidBody) del mass, ci # Create the rigid body for the Ball. Since it is a dynamic body we need to # specify mass and inertia. The former we need to do ourselves but Bullet can # do the heavy lifting for the Inertia and compute it for us.