[Question] PhysX error: PxRigidBody::setMassSpaceInertiaTensor(): components must be non-negative during training my own quadruped URDF #3257
Unanswered
xiaoxiaconfidence
asked this question in
Q&A
Replies: 3 comments
-
|
Thanks for posting this. That's interesting. I'll review with the PhysX team. |
Beta Was this translation helpful? Give feedback.
0 replies
-
|
Following up, I'll move this to our Discussions for follow up. Can you confirm you have included import_config = ImportConfig()
import_config.set_import_inertia_tensor(True)in your import script? |
Beta Was this translation helpful? Give feedback.
0 replies
-
I also encountered the same problem when I was training my robot in Isaac Lab 2.3.1.System is ubuntu 22.04, and envirpment is uv Error is: 2026-01-27T09:15:27Z [40,062ms] [Error] [omni.physx.plugin] PhysX error: PxRigidBody::setMass(): Mass must be non-negative!, FILE /builds/omniverse/physics/physx/source/physx/src/NpRigidBodyTemplate.h, LINE 424
2026-01-27T09:15:27Z [40,062ms] [Error] [omni.physx.plugin] PhysX error: PxRigidBody::setMassSpaceInertiaTensor(): Components must be non-negative, FILE /builds/omniverse/physics/physx/source/physx/src/NpRigidBodyTemplate.h, LINE 459
2026-01-27T09:15:27Z [40,069ms] [Warning] [omni.physx.fabric.plugin] FabricManager::initializePointInstancer mismatch My robot is also converted from URDF, and UrdfConverterCfg is set as follows:urdf_converter_cfg = UrdfConverterCfg(
asset_path=urdf_path,
usd_dir=os.path.dirname(dest_path),
usd_file_name=os.path.basename(dest_path),
fix_base=False,
merge_fixed_joints=False,
root_link_name="base_link",
force_usd_conversion=True,
self_collision=False,
make_instanceable=True,
replace_cylinders_with_capsules=False,
joint_drive=UrdfConverterCfg.JointDriveCfg(
gains=UrdfConverterCfg.JointDriveCfg.PDGainsCfg(
stiffness=args_cli.joint_stiffness,
damping=args_cli.joint_damping,
),
target_type=args_cli.joint_target_type,
),
)The URDF I use can be checked through the following Python script:#!/usr/bin/env python3
import xml.etree.ElementTree as ET
from pathlib import Path
import numpy as np
def check_inertia_positive_definite(ixx, ixy, ixz, iyy, iyz, izz):
I = np.array([[ixx, ixy, ixz], [ixy, iyy, iyz], [ixz, iyz, izz]])
# check symmetry
if not np.allclose(I, I.T):
return (False,)
# check if all eigenvalues are positive
eigenvals = np.linalg.eigvals(I)
if np.all(eigenvals > 0):
return True, f"Eigenvalues: {eigenvals}"
else:
return False, f"Eigenvalues: {eigenvals} (exist non-positive values)"
def check_axis_alignment(axis_xyz):
x, y, z = axis_xyz
# normalize the vector
norm = np.sqrt(x**2 + y**2 + z**2)
if norm < 1e-6:
return False, "Zero vector"
x_norm, y_norm, z_norm = x / norm, y / norm, z / norm
# check if aligned with standard axes (allow small errors)
tolerance = 1e-3
axes = {
(1, 0, 0): "X axis",
(0, 1, 0): "Y axis",
(0, 0, 1): "Z axis",
(-1, 0, 0): "-X axis",
(0, -1, 0): "-Y axis",
(0, 0, -1): "-Z axis",
}
for (ax, ay, az), name in axes.items():
if (
abs(x_norm - ax) < tolerance
and abs(y_norm - ay) < tolerance
and abs(z_norm - az) < tolerance
):
return True, name
return False, f"Not aligned ({x_norm:.4f}, {y_norm:.4f}, {z_norm:.4f})"
def check_urdf(urdf_path):
"""Check URDF file"""
tree = ET.parse(urdf_path)
root = tree.getroot()
issues = []
warnings = []
# check all link's mass and inertia matrix
print("=" * 80)
print("Check mass and inertia matrix")
print("=" * 80)
for link in root.findall("link"):
link_name = link.get("name")
inertial = link.find("inertial")
if inertial is None:
warnings.append(f"Link '{link_name}' has no inertia property")
continue
# check mass
mass_elem = inertial.find("mass")
if mass_elem is None:
issues.append(f"Link '{link_name}': no mass definition")
continue
mass = float(mass_elem.get("value", 0))
if mass <= 0:
issues.append(f"Link '{link_name}': mass value <= 0: {mass}")
elif mass < 0.001:
warnings.append(f"Link '{link_name}': mass value is too small: {mass}")
# check inertia matrix
inertia_elem = inertial.find("inertia")
if inertia_elem is None:
issues.append(f"Link '{link_name}': no inertia matrix definition")
continue
ixx = float(inertia_elem.get("ixx", 0))
ixy = float(inertia_elem.get("ixy", 0))
ixz = float(inertia_elem.get("ixz", 0))
iyy = float(inertia_elem.get("iyy", 0))
iyz = float(inertia_elem.get("iyz", 0))
izz = float(inertia_elem.get("izz", 0))
# check diagonal elements
diagonal_ok = True
if ixx <= 0:
issues.append(f"Link '{link_name}': ixx <= 0: {ixx}")
diagonal_ok = False
if iyy <= 0:
issues.append(f"Link '{link_name}': iyy <= 0: {iyy}")
diagonal_ok = False
if izz <= 0:
issues.append(f"Link '{link_name}': izz <= 0: {izz}")
diagonal_ok = False
# check if inertia matrix is positive definite
if diagonal_ok:
is_pd, msg = check_inertia_positive_definite(ixx, ixy, ixz, iyy, iyz, izz)
if not is_pd:
issues.append(
f"Link '{link_name}': inertia matrix is not positive definite - {msg}"
)
print(f"\nLink: {link_name}")
print(f" Mass: {mass}")
print(f" Inertia matrix diagonal elements: ixx={ixx}, iyy={iyy}, izz={izz}")
if diagonal_ok:
is_pd, msg = check_inertia_positive_definite(ixx, ixy, ixz, iyy, iyz, izz)
print(f" Positive definite: {'✓' if is_pd else '✗'} {msg}")
# check joint axis alignment
print("\n" + "=" * 80)
print("Check joint axis alignment")
print("=" * 80)
for joint in root.findall("joint"):
joint_name = joint.get("name")
joint_type = joint.get("type")
# fixed joint type does not need to check axis
if joint_type == "fixed":
continue
axis_elem = joint.find("axis")
if axis_elem is None:
issues.append(f"Joint '{joint_name}': no axis definition")
continue
xyz_str = axis_elem.get("xyz", "0 0 1")
try:
xyz = [float(x) for x in xyz_str.split()]
if len(xyz) != 3:
issues.append(f"Joint '{joint_name}': xyz format error: {xyz_str}")
continue
except:
issues.append(f"Joint '{joint_name}': xyz parsing failed: {xyz_str}")
continue
is_aligned, msg = check_axis_alignment(xyz)
if not is_aligned:
issues.append(f"Joint '{joint_name}': axis not aligned - {msg}")
print(f"\nJoint: {joint_name} (type: {joint_type})")
print(f" Axis: xyz=({xyz[0]}, {xyz[1]}, {xyz[2]})")
print(f" Aligned: {'✓' if is_aligned else '✗'} {msg}")
# summary
print("\n" + "=" * 80)
print("Summary")
print("=" * 80)
if issues:
print(f"\nFound {len(issues)} issues:")
for i, issue in enumerate(issues, 1):
print(f" {i}. {issue}")
else:
print("\n✓ No issues found")
if warnings:
print(f"\nFound {len(warnings)} warnings:")
for i, warning in enumerate(warnings, 1):
print(f" {i}. {warning}")
return len(issues) == 0
if __name__ == "__main__":
urdf_path = Path("urdf_path")
if not urdf_path.exists():
print(f"Error: file not exists: {urdf_path}")
exit(1)
print(f"Check URDF file: {urdf_path}\n")
success = check_urdf(urdf_path)
if success:
print("\n✓ All checks passed!")
exit(0)
else:
print("\n✗ Found issues, please fix them and check again")
exit(1) |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Question
When importing a custom quadruped robot URDF file into Isaac Lab, I encounter repeated PhysX errors during environment initialization:
✅ URDF Validation Passed:
(env_isaaclab6) admin2@admin2-Legion-R9000P-ARX8:~/sunshine/Isaaclab$ python scripts/rsl_rl/base/train.py --task RobotLab-Isaac-Velocity-Rough-JRQ-v0 --num_envs 2000
2025-07-21 12:11:16 [30,150ms] [Error] [omni.physx.plugin] PhysX error: PxRigidBody::setMassSpaceInertiaTensor(): components must be non-negative, FILE /builds/omniverse/physics/physx/source/physx/src/NpRigidBodyTemplate.h, LINE 459
2025-07-21 12:11:17 [31,589ms] [Warning] [omni.kit.notification_manager.manager] PhysX error: PxRigidBody::setMassSpaceInertiaTensor(): components must be non-negative
Beta Was this translation helpful? Give feedback.
All reactions