-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Individual bodies within compounds do not retain pointers to their positions #223
Comments
Hi Drew,
You're correct that the components of a tgCompound are represented as a
single btRigidBody and there is no way that I know of in Bullet to keep
pointers/references to the corresponding parts inside the physics
environment.
If I remember correctly we originally thought to use joints between
separate components in the physics engine so that we could maintain those
references, but that approach had its own set of issues since joints are
not truly rigid in Bullet. Also I think the calculations are considerably
heavier when using joints as opposed to a single btRigidBody.
I believe that the most straightforward solution is, as you suggested, to
store the relative positions of the component centers of mass (and sensors
positions or other locations you care about) in the tg components. When one
wants the center of mass of a particular component, it can be calculated
using the position and orientation of the single btRigidBody and the
relative position of the point of interest. There might even be a
getComponentCenterOfMass() method floating around out there, but I'm not
sure how far down that road we got.
Hope this helps,
Ryan
…On Sat, Feb 17, 2018 at 1:48 PM, Drew Sabelhaus ***@***.***> wrote:
The way that we, and Bullet, treat compound bodies, makes our current
implementation of getCenterOfMass() incorrect when rigid bodies are within
a compound.
Here's the problem:
When creating a compound in tgcreator, we make a btCompoundShape (of type
btCollisionShape), which is then passed as the collision shape when
constructing a btRigidBody. This way, btRigidBodies have exactly one
collision shape, which is made up of compound shapes, one for each
tgRigidBody we've specified.
However, since there's only one btRigidBody within a compound, that means
that the getPRigidBody() method for ANY shape within a single compound
returns a pointer to the WHOLE btRigidBody. In effect, this means that
we've got (for example), tgSpheres, tgRods, tgBoxes, etc. which are
different in NTRT but are the *same* in Bullet Physics.
Practically: when calling getCenterOfMass() from a tgRigidBody, that gets
the COM of its btRigidBody. So, when two tgRigidBodies are in a compound,
getCenterOfMass() returns the center of mass of the entire compound, NOT
each individual element.
Example: make a sphere on a stick, have them auto-compounded, and call
getCenterOfMass() on each of them (as tgModels()) anywhere within NTRT.
You'll get the same value (the COM of the compound.)
The only way to differentiate between components within a compound is to
get the btCollisionShape of the rigid body (for any component), confirm
it's a btCompoundShape, and try to get some information out of the child
btCollisionShapes that make up that compound. (For the example suggested
here - you can call getName() on the children and get back "SPHERE" and
"CylinderY.")
This creates major issues with (1) consistency, since it's misleading to
have centers of masses within NTRT that don't refer to individual objects,
and (2) not seemingly possible to get the COM of each component in a
compound.
I tried to pull out each btCollisionShape out of a btCompoundShape, and
somehow get its transform with respect to the local frame of the compound
(thinking we could call getCenterOfMass() for a compound then transform it
individually to each component), but I couldn't seem to get it to work.
Somehow, the pointers are all messed up with btCollisionShape's
getChildTransform's getOrigin and getRotation methods.
Might try to use the btCompoundShape's calculatePrincipalAxisTransform()
method, (https://pybullet.org/Bullet/phpBB3/viewtopic.php?p=&f=&t=11004),
to do what we want.
For now, *all sensor data for individual bodies, within compound bodies,
is BROKEN in NTRT.*
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#223>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AH9dbBP97c2wllbTWwTUM7Zkuz4SrVv1ks5tV0kygaJpZM4SJefZ>
.
|
Thanks Ryan! (PS - hope you're doing well!) I'm working on a solution right now - won't get the COM of the components within a compound, but will get global node positions of any model, which is probably "good enough" and is what I really wanted anyway. The general outline would be the following, inspired by Brian Mirletz' use of abstractMarker in his spines. Folks, let me know if there are unforeseen consequences here:
One issue I'm already running into is passing around btVector3 objects as pointers to a vector of floats/doubles, since it seems to be overloaded that way, and since the simulator is smart enough to dynamically re-allocate memory from previous iterations, different data is stored in the same pointers. So I've got different tgModels with the "same" nodes, since only a pointer is stored. I'm going to need to be smarted about 'const', or maybe use copy constructors when passing tgNodes into a tgModel. Any advice here? Do folks foresee any issues with dependencies? It makes me a bit concerned that we'll be including a class from tgcreator (tgNodes) in a tgModel, since I know we made a very conscious design decision to avoid that flow (creator knows about core, but core doesn't know about creator.) Thanks all! |
Hello everyone, a quick update on this, particularly as applies to the current tgDataLogger2 infrastructure. I checked and confirmed that different tgBaseRigids within the same compound rigid body point to the same btRigidBody. Example, I've got two vertebrae of a spine, each with 3 rods, and some debugging inside the tgCompoundRigidSensor constructor showed me the following: Inside tgCompoundRigidSensor constructor, we have a set of tgBaseRigids and btRigidBodies with pointers: I'm adding this as a comment to the issue because it implies the following, which is missed at some points in the codebase:
The implication here is that we will have different tgRodSensors recording data on the same rigid body. Users: be wary of this behavior, until we can provide an official debugging output/warning in the code. If anyone has incentive to fix this please do. |
The way that we, and Bullet, treat compound bodies, makes our current implementation of getCenterOfMass() incorrect when rigid bodies are within a compound.
Here's the problem:
When creating a compound in tgcreator, we make a btCompoundShape (of type btCollisionShape), which is then passed as the collision shape when constructing a btRigidBody. This way, btRigidBodies have exactly one collision shape, which is made up of compound shapes, one for each tgRigidBody we've specified.
However, since there's only one btRigidBody within a compound, that means that the getPRigidBody() method for ANY shape within a single compound returns a pointer to the WHOLE btRigidBody. In effect, this means that we've got (for example), tgSpheres, tgRods, tgBoxes, etc. which are different in NTRT but are the same in Bullet Physics.
Practically: when calling getCenterOfMass() from a tgRigidBody, that gets the COM of its btRigidBody. So, when two tgRigidBodies are in a compound, getCenterOfMass() returns the center of mass of the entire compound, NOT each individual element.
Example: make a sphere on a stick, have them auto-compounded, and call getCenterOfMass() on each of them (as tgModels()) anywhere within NTRT. You'll get the same value (the COM of the compound.)
The only way to differentiate between components within a compound is to get the btCollisionShape of the rigid body (for any component), confirm it's a btCompoundShape, and try to get some information out of the child btCollisionShapes that make up that compound. (For the example suggested here - you can call getName() on the children and get back "SPHERE" and "CylinderY.")
This creates major issues with (1) consistency, since it's misleading to have centers of masses within NTRT that don't refer to individual objects, and (2) not seemingly possible to get the COM of each component in a compound.
I tried to pull out each btCollisionShape out of a btCompoundShape, and somehow get its transform with respect to the local frame of the compound (thinking we could call getCenterOfMass() for a compound then transform it individually to each component), but I couldn't seem to get it to work. Somehow, the pointers are all messed up with btCollisionShape's getChildTransform's getOrigin and getRotation methods.
Might try to use the btCompoundShape's calculatePrincipalAxisTransform() method, (https://pybullet.org/Bullet/phpBB3/viewtopic.php?p=&f=&t=11004), to do what we want.
For now, all sensor data for individual bodies, within compound bodies, is BROKEN in NTRT.
The text was updated successfully, but these errors were encountered: