ODEDynamics: Falling Boxes ========================== :Author: Alex Dumitrache (alex@cimr.pub.ro) :Date: 2010/05/05 This is a rewrite of the `3rd PyODE tutorial`_, originally by Matthias Baas. The simulation will drop some boxes in the scene. After some time, the boxes will explode, they will be pulled back, and the cycle will repeat. .. image:: pics/boxes-drop.png First, let's create a scene and drop some boxes. .. code-block:: python import random # Create a ground plane p = Plane(lx = 5, ly = 5) # Set contact properties and initialize ODEDynamics defaultContactProps = ODEContactProperties(bounce = 0.2, mu = 5000) odeSim = ODEDynamics(gravity=9.81, substeps=2, cfm=1e-5, erp=0.8, defaultcontactproperties = defaultContactProps, use_quick_step = False, auto_add = True) def rz(ang): """Elementary rotation around Z""" return mat3(1).rotate(ang, (0,0,1)) def drop_object(): """Drop an object into the scene.""" pos = (random.gauss(0,0.1), random.gauss(0,0.1), 3) rot = rz(random.uniform(0, 2*pi)) b = Box(lx=1, ly=0.2, lz=0.2, pos=pos, rot=rot, mass=1000*1*0.2*0.2) odeSim.add(b) # Drop a box every 20 frames def onStepFrame(): if int(scene.timer().frame) % 20 == 0: drop_object() eventmanager.connect(STEP_FRAME, onStepFrame) Save the program and run it. After dropping too many boxes, the simulation will slow down, even if you have the latest Core i7 processor. Let's limit the number of boxes to 30 and add some special effects. We will also add a bit of damping; otherwise, ODE may crash due to numerical problems. .. image:: pics/boxes-explode.png Be careful when using damping together with `auto_add = True` in ODEDynamics constructor: ODE will apply damping only to bodies created *AFTER* setting the world parameters! .. code-block:: python # pyODE example 3: Collision detection # Rewritten for cgkit/ODEDynamics by Alex Dumitrache # Original code by Matthias Baas. import random objects = [] counter = 0 state = 0 # Create a ground plane p = Plane(lx = 5, ly = 5) # Set contact properties and initialize ODEDynamics defaultContactProps = ODEContactProperties(bounce = 0.2, mu = 5000) odeSim = ODEDynamics(gravity=9.81, substeps=2, cfm=1e-5, erp=0.8, defaultcontactproperties = defaultContactProps, use_quick_step = False, auto_add = True) # Add a little damping to prevent ODE from crashing odeSim.world.setLinearDamping(1e-5) odeSim.world.setAngularDamping(1e-5) odeSim.world.setMaxAngularSpeed(100) def rz(ang): """Elementary rotation around Z""" return mat3(1).rotate(ang, (0,0,1)) def drop_object(): """Drop an object into the scene.""" pos = (random.gauss(0,0.1), random.gauss(0,0.1), 3) rot = rz(random.uniform(0, 2*pi)) b = Box(lx=1, ly=0.2, lz=0.2, pos=pos, rot=rot, mass=1000*1*0.2*0.2) odeSim.add(b) objects.append(b) def explosion(): """Simulate an explosion. Every object is pushed away from the origin. The force is dependent on the objects distance from the origin. """ for b in objects: l = b.pos d = abs(l) l = max(0, 20000*(1.0-0.2*d*d)) * vec3(l[0] / 4, l[1] / 4, l[2]).normalize() b.manip.addForce(l) def pull(): """Pull the objects back to the origin. Every object will be pulled back to the origin. Every couple of frames there'll be a thrust upwards so that the objects won't stick to the ground all the time. """ for b in objects: b.manip.addForce(-500 * b.pos.normalize()) if counter % 60 == 0: b.manip.addForce((0,0,5000)) def onStepFrame(): global counter, state counter += 1 # State 1: Drop objects if state==0: if counter==20: drop_object() counter = 0 if len(objects) == 30: state=1 counter=0 # State 1: Explosion and pulling back the objects elif state==1: if counter==100: explosion() if counter>300: pull() if counter==500: counter=20 eventmanager.connect(STEP_FRAME, onStepFrame) Download the :download:`script ` and run it using:: > python viewer.py -f 50 falling-boxes.py Why `-f 50` ? The original PyODE tutorial worked at 50 fps. By default, `viewer.py` uses 30 fps. Exercises ~~~~~~~~~ * Tweak the simulation parameters. For example, set *mu = 0* and enjoy the storm :) * Try dropping boxes or spheres, at random * Make the simulation more attractive * Run the simulation at 100 fps and notice the different behavior. Try to make the simulation run in the same way, regardless of the fps * Run the simulation at 5 fps, notice the lack of accuracy in physics simulation, and fix it! .. image:: pics/balls-and-boxes.png Next steps ~~~~~~~~~~ * Compare this code with the `original PyODE tutorial`_, and try to understand how ODE works internally * Read the ODE `Manual`_, `FAQ`_ and `HOWTO tutorials`_! * Build your own demos and submit them to us :) .. _newton-balls: newton-balls.html .. _3rd PyODE tutorial: http://pyode.sourceforge.net/tutorials/tutorial3.html .. _original PyODE tutorial: http://pyode.sourceforge.net/tutorials/tutorial3.html .. _Manual: http://opende.sourceforge.net/wiki/index.php/Manual .. _FAQ: http://opende.sourceforge.net/wiki/index.php/FAQ .. _HOWTO tutorials: http://opende.sourceforge.net/wiki/index.php/HOWTO