Note
Go to the end to download the full example code.
Ball Collision Simulation#
This example simulation shows how to use pybullet to render physics simulations in fury. In this example we render the collision between a blue ball and red ball and also display a message by confirming the collision.
First some imports.
import itertools
import numpy as np
import pybullet as p
import fury
client = p.connect(p.DIRECT)
Parameters and definition of red and blue balls.
red_radius = 0.5
blue_radius = 0.5
duration = 50
# Red Ball
red_ball_actor = fury.actor.sphere(
    centers=np.array([[0, 0, 0]]), colors=np.array([[1, 0, 0]]), radii=red_radius
)
red_ball_coll = p.createCollisionShape(p.GEOM_SPHERE, radius=red_radius)
red_ball = p.createMultiBody(
    baseMass=0.5,
    baseCollisionShapeIndex=red_ball_coll,
    basePosition=[10, 0, 0],
    baseOrientation=[0, 0, 0, 1],
)
# Blue ball
blue_ball_actor = fury.actor.sphere(
    centers=np.array([[0, 0, 0]]), colors=np.array([[0, 0, 1]]), radii=blue_radius
)
blue_ball_coll = p.createCollisionShape(p.GEOM_SPHERE, radius=blue_radius)
blue_ball = p.createMultiBody(
    baseMass=0.5,
    baseCollisionShapeIndex=blue_ball_coll,
    basePosition=[-10, 0, 0],
    baseOrientation=[0, 0, 0, 1],
)
We set the coefficient of restitution of both the balls to 0.6.
p.changeDynamics(red_ball, -1, restitution=0.6)
p.changeDynamics(blue_ball, -1, restitution=0.6)
We add all the actors to the scene.
scene = fury.window.Scene()
scene.add(fury.actor.axes())
scene.add(red_ball_actor)
scene.add(blue_ball_actor)
showm = fury.window.ShowManager(
    scene, size=(900, 700), reset_camera=False, order_transparent=True
)
counter = itertools.count()
Method to sync objects.
def sync_actor(actor, multibody):
    pos, orn = p.getBasePositionAndOrientation(multibody)
    actor.SetPosition(*pos)
    orn_deg = np.degrees(p.getEulerFromQuaternion(orn))
    actor.SetOrientation(*orn_deg)
apply_force = True
tb = fury.ui.TextBlock2D(position=(0, 600), font_size=30, color=(1, 0.5, 0), text="")
scene.add(tb)
scene.set_camera(
    position=(0.30, -18.78, 0.89), focal_point=(0.15, 0.25, 0.40), view_up=(0, 0, 1.00)
)
Timer callback to sync and step simulation every second.
def timer_callback(_obj, _event):
    global apply_force
    cnt = next(counter)
    showm.render()
    red_pos, red_orn = p.getBasePositionAndOrientation(red_ball)
    blue_pos, blue_orn = p.getBasePositionAndOrientation(blue_ball)
    # Apply force for the first step of the simulation.
    if apply_force:
        p.applyExternalForce(
            red_ball, -1, forceObj=[-40000, 0, 0], posObj=red_pos, flags=p.WORLD_FRAME
        )
        p.applyExternalForce(
            blue_ball, -1, forceObj=[40000, 0, 0], posObj=blue_pos, flags=p.WORLD_FRAME
        )
        apply_force = 0
    sync_actor(blue_ball_actor, blue_ball)
    sync_actor(red_ball_actor, red_ball)
    # Get various collision information using `p.getContactPoints`.
    contact = p.getContactPoints(red_ball, blue_ball, -1, -1)
    if len(contact) != 0:
        tb.message = "Collision!!"
    p.stepSimulation()
    if cnt == 50:
        showm.exit()
showm.add_timer_callback(True, duration, timer_callback)
interactive = False
if interactive:
    showm.start()
fury.window.record(scene, size=(900, 700), out_path="viz_ball_collide.png")