Incorrect robot mass?

Hey all,

I have a robot, and I want to know its mass. Usually, to do that, one can use the UsdPhysics.MassAPI. But if use it, the mass I get is incorrect.

The mass I am getting is 29.302, which is what I would expect. But the actual mass of the robot is 25990.0.
To check that the mass is correct, I am applying a positive force on the z axis that is equal to: mass * 981.1. This should make the object slowly fly upwards. It works well with cubes, and simple rigid bodies, but for the robot it does not work, unless I multiply that force by 887.25. Does someone know why?

I have attached the robot I am trying to weight:
heron.usd (2.0 MB)

Here is the code I am using to get the mass of my robot:

import omni
from pxr import Usd, UsdGeom, Gf, UsdPhysics
from omni.physx.scripts import utils
import math
M = 0
curr_prim = stage.GetPrimAtPath("/")
for prim in Usd.PrimRange(curr_prim):
		MassAPI = UsdPhysics.MassAPI.Get(stage, prim.GetPath())
		mass = MassAPI.GetMassAttr().Get()
		if mass:
			M += mass

I’ll answer myself, the issue comes from the fact that every single rigid body is assigned a mass by the simulator. And this is true even if this rigid body has no MassAPI associated. I don’t know which values are used though. But assigning a bunch of small masses to every-single rigid body of my robot solved my problem.

I think this may be a bug, or it should be clearer that without defined mass, the mass is picked based on some density function or what not.

Hello, @antoine.richard!
That’s correct, in order for the simulation to work, every single rigid body needs to have a mass. The default density is 1000kg/m^3, and it uses the body geometry for the volume. Here’s the documentation for the mass properties: USD Documentation : Rigid Body Physics in USD Proposal

  • Parents’ explicit total masses override any mass properties specified further down in the subtree.
  • Density has lower precedence than mass, so explicit mass always overrides implicit mass that can be computed from volume and density.
  • A density in a child overrides a density specified in a parent for all of the subtree under the child.
  • A density specified via PhysicsMassAPI, even if it is inherited from a node higher in the tree, overrides any density specified via a material (see PhysicsMaterialAPI later in this document).
  • Implicit mass at any node is the computed volume of collision geometry at that node times the locally effective density, plus the implicit masses of all children in the subtree.
  • Density is assumed to be 1000.0 kg/m 3 (approximately the density of water) for volume computation when no other density is specified locally, or in rel-ed materials either locally or higher up in the tree, and this value is converted into the collider’s native units prior to being used for mass computation.
  • Mass is assumed to be 1.0 in the mass units used when none is provided explicitly, and there are no collision volumes to derive from.

Thanks ! It is weird that masses are assigned by default to rigid-bodies. A lot of time no masses are assigned to meshes as they are only here for collisions or display. But thanks, In the future I’ll know.

Just to clarify your last comment: You can have a collision mesh with no Rigid body API. The Rigid Body API is exclusively for objects that move, and therefore may be subject to the force of gravity and need a mass property.

there are Three APIs in this discussion:

  • Collision API.
  • Mass API.
  • Rigid Body API.

In order to make them all independent, a default mass is applied if no Mass API is provided on a rigid body. An independent Mass API makes no sense indeed, so we hide that option when a prim or any of its parents does not have the rigid body API applied.

A rigid body may have no collision too, and may have the gravity parameter ignored (for example a proxy rigid body for a 2DOF link between two rigid bodies, or a rotating light that doesn’t need neither)

Ah, ok. So say I have a robot, And that robot is made of multiple components that are all attached and cannot move relatively to the chassis. Can I have only one rigid body, the chassis, while the other bodies are just collisions? Will the robot still move? In that setup, would I be able to apply a force to one of the collision bodies?

let’s use the following as an example:

- Robot
  - Chassis 
  - Bumper
  - Mudflap
  - (etc...)

the Real world, the bumper and mudflap are two components that are screwed on the robot chassis. In the simulation though, they may all become a single rigid body. You would create a parent prim that would be the rigid body, and you can have multiple components inside to generate its mass and collision properties. everything is compound on the parent prim with the rigid body api. so it would look something like this:

- Robot
  - Chassis (Xform, Ridig Body)
    - Chassis mesh (Mesh, Collision + Mass)
    - Bumper (Mesh, Collision + Mass)
    - Mudflap (Mesh, Collision + Mass)
  - (etc...)

In this case, when you want to apply a force to the bumper, for instance, you’d actually apply a force to the chassis directly, and all three objects would move as a unit.