Panda Bullet


#621

I download the last buildbot (1.9.0) but I have always the margin problem. That’s really strange and I guess it will be hard to fix if you can’t reproduce the issue.


#622

I am currently getting the same error as reported here on arch linux 64 bit with panda 1.8.0

I am getting this error both by both by doing nodePath.setPos() and node.setLinearVelocity(). This is set before I’ve done any stepping with Bullet World.

Thank you again for your help, time, and work!


#623

I will ask rdb about the Bullet versions on the buildbot machines. Maybe we are still using 2.78.


#624

I found out something interesting on “Overflow in AABB, object removed from simulation” when using setPos on a nodepath. It only happens when a debug node is set in BulletWorld. This happens in 1.8.0 and in the most recent 1.9 builds. Let me know if you need additional information.


#625

Can’t make any sense of this. What NodePath (the debug renderer, a rigid body, …)? What is the NodePath transform before you call setPos, and what values do you use in setPos? What are the config setting and how is the setup for the BulletWorld?

It might be best if you try to come up with some script which reproduces your issue. Until then I assume that you simply moved a rigid body beyond the world boundaries.


#626

I think I’ve found a bug in the collision filtering. If there is no collision mask applied when you attach a rigid body, then it it is not possible to change the collision mask afterwards. There is no error, it just has no effect. You can see what I mean by swapping the two commented lines in the code below. Is this a bug or some sort of optimization similar to not calling setMass to make a static body?

In the example here, the boxes should fall through the plane since their group flags are specifically set not to collide. They will collide unless the order of the two lines is changed. I am using a fairly recent version of the code from CVS. Would have to investigate a bit to find out exactly when.

from panda3d.core import Point3, Vec3, BitMask32, loadPrcFileData
loadPrcFileData('', 'bullet-filter-algorithm groups-mask')
from panda3d.bullet import BulletWorld, BulletPlaneShape, BulletBoxShape, \
BulletRigidBodyNode, BulletDebugNode
from direct.showbase.ShowBase import ShowBase

class Game(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
        self.cam.setPos(0, -20, 4)
        self.cam.lookAt(0, 0, 0)
        self.world_np = self.render.attachNewNode('World')
        self.debug_np = self.world_np.attachNewNode(BulletDebugNode('Debug'))
        self.debug_np.show()
        self.world = BulletWorld()
        self.world.setGravity(Vec3(0, 0, -9.81))
        self.world.setDebugNode(self.debug_np.node())
        self.world.setGroupCollisionFlag(0, 1, False)
        self.add_ground()
        self.add_box(Point3(1, 0, 1))
        self.add_box(Point3(3, 0, 1))
        self.add_box(Point3(1.25, 0, 3))
        self.taskMgr.add(self.update, 'updateWorld')

    def add_ground(self):
        shape = BulletPlaneShape(Vec3(0, 0, 1), -1)
        nodepath = self.world_np.attachNewNode(BulletRigidBodyNode('Ground'))
        nodepath.node().addShape(shape)
        nodepath.setPos(0, 0, -1)
        nodepath.setCollideMask(BitMask32.bit(0))
        self.world.attach(nodepath.node())

    def add_box(self, pos):
        shape = BulletBoxShape(Vec3(0.5, 0.5, 0.5))
        nodepath = self.world_np.attachNewNode(BulletRigidBodyNode('Box-1'))
        nodepath.node().setMass(1.0)
        nodepath.node().addShape(shape)
        nodepath.setPos(pos)
        ########## HERE ###########
        # swap the order of these two lines for different behaviour
        self.world.attach(nodepath.node())
        nodepath.setCollideMask(BitMask32.bit(1))
        ###########################

    def update(self, task):
        self.world.doPhysics(globalClock.getDt())
        return task.cont

Game().run()

#627

This is an interesting finding, teedee. I’m pretty sure Bullet did behave different before updating to 2.80. Anyway, I do have some kind of explanation what is going on:

When adding a body to a world Bullet checks a first time if this body overlaps with other bodies. Since in your case you have an infinite plane as ground object (which has an infinite bounding box) Bullet marks the box/plane pairs for collision, if the mask has not yet been set (the initial mask is 32 bits ON). This means a persistent manifold point gets created, and it never gets dropped because the overlap in bounding boxes never ends.

So the “safe” way is to first set the mask, and then add the body to the world.

What makes me worried is that I am no longer sure that changes to the collision masks might or might not have an effect if done sometime during the simulation steps. I definitely have to dig deeper. Maybe there is a way to force a re-evaluation of the broadphase cache.


#628

What I’ve done as a workaround is set a zeroed “BitMask32()”, and later change it as needed after attaching. This seems to work fine.


#629

Just wanted to say thanks for integrating Bullet into Panda. We were using ODE since at the time the work on Bullet had not even started yet. We finally made the decision to switch to Bullet since we have been struggling with stability problems in ODE for a long time. A risky proposition with only about 2 months to go!

I found the API to be excellent and I was able to convert our physics code to Bullet in just 4 days, with the difficult part mostly being dealing with differences in constraints between ODE and Bullet. Our game is now running faster and more stable than ever.

Thanks!


#630

Is there a way to get all nodes changed by the last doPhysics() call? Is it fast enough to do every frame?

I need this to synchronize world state over the network. Idea is to keep track of all nodes changed from previous network packet and send the updated values in the next packet. I can keep track of changes my own code makes, but not the Bullet. Alternative is to compare to the unmodified copy of everything that can possibly change, but this solution does not sound good at all.

Or maybe there are means to find all PandaNodes changed since the last redraw, or something. That would work, too.


#631

Neither Bullet itself nor the Panda3D module provide a way to find all objects which have changed. Changed is a very wide term here. It might be a change between sleeping/awake, a change in mass or shape (user-induced!) or anything else.

Regarding changes in transform (position/orientation) there might be a way if you use a CVS version after December 2012. You have to work on the C++ level to expose some private attributes, and it works only for rigid body nodes:

BulletRigidBodyNodes have a private member TransformState, which implements the Bullet btTransformState interface. The TransformState tracks if there have been changes to the rigid bodies transform within a simulation step (via the private boolean member _dirty). The dirty state is reset at the end of a simulation step, but this should be no problem. Tell me if you want to go this way.


#632

CVS builds are fine. Rigid bodies are good enough, too. Hacking into C++ is a bit scary, but I can do that if really need be.

There’s another thing that troubles me, though. Let me clarify.

If I take the _dirty-bit approach, do I have to loop through all RigidBodyNodes each tick checking _dirty?

Because on the other hand, I can loop through all the same RigidBodyNodes each network frame checking TransformStates for change. Which doesn’t seem terribly less efficient. TransformStates are immutable, so it is a pointers comparison. Moreover, at that higher level it is possible to consider only RigidBodies that are potentially movable in my game.

So, the question is. Is there something clever in the way RigidBodyNodes are stored internally, that makes it possible to retreive all _dirty nodes fast? Without looping through all RigidBodyNodes. If not, it doesn’t seem to worth it.

And another question. Do you know if the same problem can be easily solved in other physics engines? ODE, PhysX?.. I’m not particulary tied to Bullet yet, so it may worth it.


#633

First let me correct my previous post: it’s not BulletRigidBodyNode::TransformState, but BulletRigidBodyNode::MotionState, implementing btMotionState. It has been a bit late, sorry for the typo.

When you collect (and reset!) your own dirty flags is up to you, but cycling through the list of rigid bodies is probably much faster than any other solution (emitting event, adding to a dynamic list, …).

A quick approach would be to add a second bool member to BulletRigidBodyNode::MotionState, e. g. _was_dirty. Set this to TRUE at the same time as _dirty is set to TRUE. Then add a method with visibility PUBLISHED to BulletRigidBodyNode which retrieves and resets the _was_dirty flag. Now you could even collect the data from Python, if you like.

I could provide modified source files for BulletRigidBody if you feel uneasy with C++ coding.


#634

_was_dirty approach is better than _dirty, that’s for sure. No per-tick calculations needed.

Still, I can not see why checking _was_dirty is significantly faster than calling BulletRigidBodyNode.getTransform() and comparing it to previously saved TransformState for this node. Previous TransformState can even be stored internally in the node itself, using PandaNode.setPythonTag().

Therefore I only consider _was_dirty as an optimization technique. It should still be faster than comparing TransformStates in python, but not significantly faster. Unless, as I mentioned, there’s a clever way to get all _was_dirty nodes without cycling through all RigidBodyNodes. Like an internal list to add nodes to at the time _was_dirty is set first time on a node.


#635

BulletRigidBodyNode.getTransform() returns a (const) pointer to a new instance of a TransformState object. You can’t just compare the pointer addresses or the Python ids - you have to compare the full content. This is 4x4=16 floating point number. Also you should consider numerical precision, so you have to compare with a small epsilon. This is way slower than checking a boolean value, right?

But you are right, you should go with the most easy to implement way first, and consider optimizing performance only when needed.


#636

Oh. What a gotcha. I thought getTransform() implements a cache to take advantage of immutability.

Well, you are right then: _was_dirty is the way to go.

I would really appreciate if you helped me with C++ part. I’m totally at sea with low-level stuff and probably going to waste lots of time on trivial things before doing any real work. Anything helps.

Not too urgent as I can prototype stuff using TransformState comparison anyway.

Thanks in advance.


#637

Hello everyone

thank you very much for your work to include Bullet into Panda3d! It is already really great.

However, now I run into a problem I could not solve on my own. Suppose I have a BulletHingeConstraint connecting two rigid bodies. How could I determine the angular velocity at which the bodies are rotating around this joint? I found an answer in the Bullet forums proposing calculating the dot product of the hinge axis and the difference of the two angular velocity vectors of the bodies. Unfortunately, it seems that the BulletHingeConstraint in Panda does not provide a method to obtain the hinge axis. So how I could I solve this task?

Thank you very much for your help!
Cheers
Timo


#638

Here is the Bullet C++ API documentation for the btHingeContraint (wrapped by BulletHingeConstaint). Can you point me at the method you are missing? Maybe we can expose this method too.

bulletphysics.com/Bullet/BulletF … raint.html


#639

Does anyone have code for making ragdolls?
Couldn’t find anything in the manual and forums.


#640

Any chance we can get the getDebugNode() method added to BulletWorld? Does this method exist in the Bullet api?