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.63k stars 2.88k forks source link

Best way to implement RigidBodies in PhysicsClientC_API #1328

Closed not-fl3 closed 7 years ago

not-fl3 commented 7 years ago

Hello!

I am working on PhysicsClient rust-bindings. (http://github.com/not-fl3/bulletrs)

I found that only MutlyBodies is exposed to PhysicsClient. I made my own implementation of RigidBodies in SharedMemory client (https://github.com/not-fl3/bullet3/commits/rustbindings) but I have a strong feeling that I am doing something wrong.

So here are my questions:

Any other advices on building rust (or C in general) bindings?

erwincoumans commented 7 years ago

You can also create rigid bodies from the C-API: pybullet.loadURDF("cube.urdf", useMaximalCoordinates=True) and also programmatically, providing the same flag: pybullet.createCollisionObject(...), pybullet.createMultiBody(..., useMaximalCoordinates=True). See http://pybullet.org. At the moment, multibody is better supported, works better for robots, but rigid body performs a bit better. You can mix them, there is two-way interaction. Theoretically, a btMultiBody base without link is identical to a btRigidBody, but the implementation is more heavy / slower. Note that we moved away from the Bullet 2.x C++ API, the C-API is more abstract, to allow different physics implementations.

On the rust binding: you could try autogenerating a C binding from PhysicsClientC_API.h. I just created a Bullet C-API binding to C# for Unity, you can autogenerate bindings from the C header file. Here is some example:

https://github.com/bulletphysics/bullet3/pull/1327 in particular the readme.txt.

This is a bit more low-level than pybullet: you need to manually create the commands and submit and wait status. So you canlook at the pybullet.c or b3RobotSimulator.cpp how things are done.

not-fl3 commented 7 years ago

@erwincoumans Thanks for the answer!

And thanks for the tip about useMaximalCoordinates, it helped a lot!

But there is a problem: in PhysicsDirect.cpp, postProcessStatus body created that way assumed as MultiBody, not RigidBody. resulting SEGFAULT in processBodyJointInfo. Only in direct, even in SharedMemory connection type it works fine. Disabled calling that method as a temporary workaround.

Can't found createCollisionObject, did you mean createCollisionShape?

Theoretically, a btMultiBody base without link is identical to a btRigidBody

In that case - I can't get how to use methods like setAgularFactor or setLinearVelocity on btMultiBody. Can you please point me that part of documentation I am missing?

I am doing it this way (and it works only on bodies created with UseMaximumCoordinates flag or with my hacky CreateRigidBody command): https://github.com/not-fl3/bullet3/commit/3db95e56931f702d6efe0fbc5f2c05aa5f90655c is there any better options?

erwincoumans commented 7 years ago

postProcessStatus body created that way assumed as MultiBody, not RigidBody.

Are you using the latest version of the Bullet repository? If so, please provide a small reproduction case.

I'm assuming you are using pybullet or the C-API. 'setAngularFactor' and 'setLinearVelocity' doesn't exist in pybullet and in the C-API, don't mix it up with the Bullet 2.x C++ API. There is a resetBaseVelocity and resetJointState. Many features are not hooked up to btRigidBody, just btMultiBody. Why do you really need maximalCoordinates? Probably easier if you ask what you are trying to achieve.

Yes, I meant 'createCollisionShape. Also, the underlying PhysicsServerCommandProcessor is not meant to be extended by most users.

not-fl3 commented 7 years ago

I am working on general purpose Rust bindings, so my long term goal - to have access to entire bullet's api from Rust side. You can check how its going here: https://github.com/not-fl3/bulletrs, examples is simplified cases from my game :)

I am not sure that this will be enough, but here is use case from my game I am working on just now:

Create a body with compound mesh(rigid or multi, it doesn't really matters), set it position/rotation, forbid rotation in some axis(setAngularForce doing that job perfectly) and have an option to apply forces(applyCentralImpulse and applyImpulse in btRigidBody). And get body motion back to my engine. MotionState will be the best, but just GetPositionAndOrientation wors for now too.

I already made most of this - by adding commands to CommandProcessor. Not sure that it was good idea, but it worked.

'setAngularFactor' and 'setLinearVelocity' doesn't exist in pybullet and in the C-API

well, setLinearVelocity was bad example - resetBaseVelocity is doing exectly this. But what about setAngularFactor? Or something else not available from PhysicsClient? It not supposed to be in C API, or it just not yet added there? I am fine to use my own branch(or made a PR with that methods) if adding that methods(or something like this) is in roadmap of PhysicsClient.

not-fl3 commented 7 years ago

Are you using the latest version of the Bullet repository? If so, please provide a small reproduction case.

Just reproduced the same with pybullet from pip.

import pybullet as p

p.connect(p.DIRECT) # it was perfectly with p.GUI
body = p.createCollisionShape(p.GEOM_SPHERE)
p.createMultiBody(10, body, useMaximalCoordinates=1)

That code segfaults with:

#0  bParse::bDNA::flagEqual (this=0x555555ac1520, dna_nr=1831469177) at Extras/Serialize/BulletFileLoader/bDNA.cpp:122
#1  0x00007f5d45139615 in bParse::bFile::readStruct (this=this@entry=0x7ffffffeee70, head=head@entry=0x7f5d2b844e54 "a", dataChunk=...) at Extras/Serialize/BulletFileLoader/bFile.cpp:666
#2  0x00007f5d4513bc6d in bParse::btBulletFile::parseData (this=0x7ffffffeee70) at Extras/Serialize/BulletFileLoader/btBulletFile.cpp:161
#3  0x00007f5d4513b2db in bParse::bFile::parseInternal (this=0x7ffffffeee70, verboseMode=0, memDna=0x555555bb9650 "SDNANAME\204\001", memDnaLength=11936)
    at Extras/Serialize/BulletFileLoader/bFile.cpp:315
#4  0x00007f5d4513b6c5 in bParse::btBulletFile::parse (this=this@entry=0x7ffffffeee70, verboseMode=verboseMode@entry=0) at Extras/Serialize/BulletFileLoader/btBulletFile.cpp:346
#5  0x00007f5d44ef6ca7 in PhysicsDirect::processBodyJointInfo (this=0x555555be6810, bodyUniqueId=0, serverCmd=...) at examples/SharedMemory/PhysicsDirect.cpp:613
#6  0x00007f5d44ef8101 in PhysicsDirect::postProcessStatus (this=this@entry=0x555555be6810, serverCmd=...) at examples/SharedMemory/PhysicsDirect.cpp:867
#7  0x00007f5d44ef9ac6 in PhysicsDirect::processServerStatus (this=0x555555be6810) at examples/SharedMemory/PhysicsDirect.cpp:216
#8  0x00007f5d44f2df54 in b3SubmitClientCommandAndWaitStatus (physClient=physClient@entry=0x555555be6810, commandHandle=commandHandle@entry=0x7f5d2b836038)
    at examples/SharedMemory/PhysicsClientC_API.cpp:1659
#9  0x00007f5d44ecfb8b in pybullet_createMultiBody (self=<optimized out>, args=<optimized out>, keywds=<optimized out>) at examples/pybullet/pybullet.c:5400
....
erwincoumans commented 7 years ago

I'll fix that crash right away, thanks for the report.

I still suggest leaving the option open for multibody (the default), since it has several benefits, such as much stiffer joints, and better joint motors. You can achieve an effect like 'angular factor' using multibody as well. For example, this video is a multibody that only moves in 2D: https://www.youtube.com/watch?v=_6qWoDCPde0 You would start with a fixed base, and then add the degrees of freedom you allow. The deep reinforcement learning gait/locomotion would also be very nice for games. See my twitter feed for some ideas: https://twitter.com/erwincoumans

erwincoumans commented 7 years ago

I just ran your script, and there is no crash here. You branch is many commits behind, and the pip/pypi was out-of-date too, the 1.4.6 version I submitted yesterday is more up-to-date. Can you run pip uninstall pybullet and pip install pybullet again, and try it? Also update your clone?

not-fl3 commented 7 years ago

My bad, I had pybullet-1.4.5 in pip. Updating now.

not-fl3 commented 7 years ago

Yes, its fixed in 1.4.6. Sorry for false report :(

erwincoumans commented 7 years ago

Can you try updating your fork and let me know if your crash is really fixed?

not-fl3 commented 7 years ago

Updated, it works perfectly now, thanks :)

not-fl3 commented 7 years ago

I tried really hard to use only PhysicsClient, but came to the conclusion being really great for robotics simulation, it does not work well as general purpose physics/collision engine for me. I still cant understand the idea behind abstraction over rigid and multi bodies. So many functions are not exposed to PhysicsClient - for example, CharacterControllers, MotionStates, TriMeshes. Also its not possible to use Bullet Collision just for collisions through PhysicsClient.

Will PhysicsClient fit that niche? Or its better stop trying to add missing features to CommandProcessor and call C++ directly?

erwincoumans commented 7 years ago

All of those should be possible with the PhysicsClient C-API, no need to dig under the hood. TriMeshes -> in URDF use concave="yes" attribute, programmatically (createCollisionShape), use the GEOM_MESH type with GEOM_FORCE_CONCAVE_TRIMESH flag. CharacterControllers -> This is a custom action, best to use a C++ plugin that ticks each callback, applying your custom forces etc. The plugin system is new, see the vrSyncPlugin for an example. collisions and raycast-> there is an API for that. See the first page (index) of http://pybullet.org. If you prefer more direct/low level access, use the Bullet 2.x C++ API. Let's close this issue.

not-fl3 commented 7 years ago

Thanks for the answer, I really appreciate your help. Sorry for bothering with the same questions for so many times, it's quite hard to decide which way is better especially without the full picture. I think you give me enough information now, so thank you again!