bulletphysics / bullet3

Bullet Physics SDK: real-time collision detection and multi-physics simulation for VR, games, visual effects, robotics, machine learning etc.
http://bulletphysics.org
Other
12.36k stars 2.85k forks source link

Visualizing multiple pyBullet server instances #4290

Open manas96 opened 2 years ago

manas96 commented 2 years ago

Hi, I'd like to spawn multiple instances of the physics server, send them some geometry, start them and then combine their output in a single GUI window. I'm trying to repurpose the existing 3D rendering infrastructure that pyBullet provides. Here's what I'm trying to do so far:

p0 = bc.BulletClient(connection_mode=pybullet.DIRECT)
p1 = bc.BulletClient(connection_mode=pybullet.DIRECT)
p0.loadURDF("r2d2.urdf")
p1.loadSDF("stadium.sdf")

# This will be used to render the output from p0 and p1 both
pgui = bc.BulletClient(connection_mode=pybullet.GUI)

while 1:
    p0.stepSimulation()
    p1.stepSimulation()

    # somehow get all geometry information
    geom0 = p0.getGeom()
    geom1 = p1.getGeom()
    # send all geometry to pgui and render it
    pgui.send(geom0, geom1)

I'm currently looking into the saveState() and restoreState() methods to do this but this feels very hacky, so my question is is there a better way to do this? Note that the geometry on both "worker" servers might not be the same.

Edit Here's the code I'm trying to work with:

import pybullet_utils.bullet_client as bc
import pybullet as p
import pybullet_data
import time
STATE_FILE = 'state.bullet'
SCENE_FILE = 'scenes/spiralWall.bullet'

def setupServer(handle):
    handle.setAdditionalSearchPath(pybullet_data.getDataPath())
    handle.setPhysicsEngineParameter(deterministicOverlappingPairs=1)

    startOrientation = handle.getQuaternionFromEuler([0, 0, 0])
    handle.loadURDF("r2d2.urdf", [0, 0, 1], startOrientation)
    handle.loadURDF("plane.urdf")
    handle.setGravity(0, 0, -10)

p1 = bc.BulletClient(connection_mode=p.DIRECT)
setupServer(p1)

pgui = bc.BulletClient(connection_mode=p.GUI)
#setupServer(pgui)

while 1:
    p1.stepSimulation()

    p1.saveBullet(STATE_FILE)
    pgui.restoreState(fileName=STATE_FILE)

    pgui.stepSimulation()

    time.sleep(1. / 240.)

Which gives me the error:

Traceback (most recent call last):
  File "C:\Users\m84241864\Desktop\projects\bullet\python\multi_server.py", line 43, in <module>
    pgui.restoreState(fileName=STATE_FILE)
pybullet.error: Couldn't restore state.

I am able to restore p1's state in pgui if I uncomment #setupServer(pgui). But I would like to be able to restore geometry that is previously unknown to pgui. Also, how do I debug pybullet.error's?

manas96 commented 2 years ago

I was able to hack something together by maintaining two copies of geometry objects. That is, if we have geometries {X,Y} on p1, {A,B} on p2, I maintain geometries {X,Y,A,B} on the GUI server and update their positions every frame. But happy to hear if there is a cleaner solution.

yogha001 commented 1 year ago

Hi @manas96, I am currently working on the same issue and I was wondering if you have found a solution for it since then? Or @erwincoumans could you help us ?

manas96 commented 1 year ago

Hi @yogha001, I ended up building on top of the workaround I posted above.

yogha001 commented 1 year ago

Hi @manas96, so happy you replied. Well i'm not really working on excatly the same issue. Here is the issue I'm working on, just made a post: https://github.com/bulletphysics/bullet3/issues/4402