Get Bullet Ridid Body absolute Position

Hello,

Using Bullet engine and I all I need is to getPos, and getHpr but from a bullet object (My helicopter), which from my understanding is not possible. When I attach the helicopter and call the ‘getHpr’ or the ‘getPos’ it returns 0’s even though my object is moving with the bullet object it is attached too. I guess my question is, if there is some work around like attaching a emptyNode or something just to get the object orientation?

Here is some reference code;

    # SHIP
    boundBox = BulletBoxShape(Vec3(3, 2, .5))
    self.aircraftNP = BulletRigidBodyNode('Box')
    self.aircraftNP.setMass(800)
    self.aircraftNP.addShape(boundBox)
    airNP = render.attachNewNode(self.aircraftNP)
    self.world.attachRigidBody(self.aircraftNP)
    self.aircraft = loader.loadModel('models/drone.gltf')
    self.aircraft.flattenLight()
    self.aircraft.reparentTo(airNP)
    self.cam.setY(-20)
    self.cam.setZ(5)
    self.cam.lookAt(airNP)
    self.cam.reparentTo(airNP)

So self.cam.getPos() or self.cam.getHpr() returns nothing
neither does self.aircraft.getPos() …

Doing something like;
self.aircraftNP.getInertia())
self.aircraftNP.getLinearVelocity())
self.aircraftNP.getTotalForce())
That works great but all I want in the world POS ???

Any pointers would be greatly appreciated. If I get all this to work then I will start posting content on www.shenko.org

Thank You, for your time

In short, “getPos” and “getHpr” (and other such methods, like “getScale”), when called with no parameters, return the relevant data relative to the NodePath’s parent.

Thus, if the NodePath that you’re examining is a child of some other NodePath, and is left at (0, 0, 0) relative to that other NodePath, then calling “getPos()” on it will always return (0, 0, 0).

However, those same methods also accept an optional parameter. That parameter is another NodePath, and indicates that the data should be given relative to said NodePath.

Thus, if your world-root is “render” (as is the standard case), then you can get a NodePath’s position relative to the world-root by calling “getPos(render)” on your NodePath.

A quick demonstrative example:

# Set up our NodePaths
parentNP = render.attachNewNode(PandaNode("parent"))
myNP = parentNP.attachNewNode(PandaNode("my np"))

# Set the position of "myNP" to be (0, 0, 0) relative to
# its parent.
myNP.setPos(0, 0, 0)

# Now, move the parent NodePath so that we
# have a non-zero world-position for our NodePath
parentNP.setPos(5, 7, 1)

# And now, let's examine the position of our NodePath:
print (myNP.getPos()) # Shows a position of (0, 0, 0)--
                      # i.e. the NodePath's position
                      # relative to its parent
print (myNP.getPos(render)) # Shows a position of (5, 7, 1)--
                            # i.e. the NodePath's position
                            # relative to the given NodePath,
                            # "render"

Similarly, you can get a NodePath’s HPR relative to another NodePath in the same way, by including the other NodePath in the call to “getHpr” (or “getH”, “getP”, and “getR”). Likewise for “getScale”, etc.

Furthermore, you can do the inverse: you can set these values relative to another NodePath in the same way, by providing a NodePath as the first parameter to a call to “setPos”, “setHpr”, etc., as I recall.

Thank Thaumaturge for your help, however I think I forgot to mention Im working with a bullet object. I get the following error;

AttributeError: 'panda3d.bullet.BulletRigidBodyNode' object has no attribute 'getPos'

I remember reading something somewhere a long time ago about this problem, but hours of googling documentation and forums yeilded nothing.

1 Like

#----------SOLVED--------------#

This worked for me;

self.aircraftNP.getTransform().getPos()

Also works with getHpr() for rotational position (Pitch, Roll, Yaw)

I want to thank you again @Thaumaturge I was so close to giving up :slight_smile:

1 Like

I’m glad that you got it working! :slight_smile:

If I may, I think that it’s often more convenient to keep a reference to a NodePath rather than a node: As you found here, NodePath provides a variety of convenience functions that the node-classes do not–and still gives you access to the node if called for. That last is done by calling “node()” on the NodePath.

So, in your example above, you might instead have something like this:

# Here, we don't keep a reference to the node--
# it's just a local variable
aircraftNode = BulletRigidBodyNode('Box')
# ... Omitting setup of the node for brevity ...

# Conversely, we >do< keep a reference to the NodePath
self.airNP = render.attachNewNode(aircraftNode)

# ... And the rest of your setup here, modified as appropriate
# to the above changes ...

Then, later, you can do something like this:

# To get the object's position
pos = self.airNP.getPos(render)

# To get the Bullet-object's inertia
inertia = self.airNP.node().getInertia()

# Or, if you're going to work with the node
# multiple times within the same function or loop:

node = self.airNP.node()
inertia = node.getInertia()
node.setLinearVelocity(someVelocityValue)
# etc...
1 Like

Great, I’ll try and work that into the script. You’ve been a great help.

1 Like