在PyBullet中导入的模型(尤其是URDF模型)没有质量,根本原因在于模型文件中的物理参数定义不完整或格式不正确。这会导致PyBullet无法正确计算动力学行为,表现为零件不受重力影响、无法碰撞或无法施加力控制。以下是具体原因和解决方案的详细分析:

一、主要原因分析表

原因类别具体问题典型表现
1. URDF文件定义缺失<inertial> 标签完全缺失或定义错误零件“飘在空中”,重力无效,碰撞后行为异常
2. 质量属性为零<mass> 值被设为0或极小值零件轻微受力即高速运动,或运动计算不稳定
3. 惯性矩阵错误<inertia> 矩阵值全为零或不合理零件旋转行为异常(不受转矩影响或旋转失控)
4. 视觉与碰撞模型分离仅定义了视觉网格,未指定碰撞形状零件可以显示,但会穿透其他物体,无碰撞检测
5. 单位制不统一模型文件(如STL)与URDF单位不一致质量、尺寸感知错误,导致动力学行为比例失调
6. 加载参数错误使用了 useFixedBase=True 等标志零件被固定在世界坐标系上,看似“无质量”

二、诊断与解决方案

第一步:快速诊断

在导入模型后立即检查质量属性:

import pybullet as p

# 加载模型
obj_id = p.loadURDF("your_part.urdf")

# 检查质量属性
mass = p.getDynamicsInfo(obj_id, -1)[0]  # -1 表示基座
print(f"物体质量: {mass} kg")

# 检查碰撞形状
collision_shape = p.getCollisionShapeData(obj_id, -1)
print(f"碰撞形状数据: {collision_shape}")

第二步:修复URDF文件(最常见原因)

确保每个<link>都包含正确的<inertial>标签:

错误示例:

<link name="part_link">
  <visual>
    <geometry><mesh filename="part.stl"/></geometry>
  </visual>
  <!-- 缺少 inertial 标签! -->
</link>

正确示例:

<link name="part_link">
  <visual>
    <geometry><mesh filename="part.stl"/></geometry>
  </visual>
  <collision>
    <geometry><box size="0.1 0.1 0.1"/></geometry>
  </collision>
  <inertial>
    <mass value="1.0"/>  <!-- 质量(千克) -->
    <origin xyz="0 0 0"/> <!-- 质心位置偏移 -->
    <inertia ixx="0.001" ixy="0" ixz="0"  <!-- 惯性张量 -->
             iyy="0.001" iyz="0" 
             izz="0.001"/>
  </inertial>
</link>

三、总结流程

遇到零件无质量问题时,按此流程排查:

运行诊断脚本 → 确认质量是否为0

检查URDF文件 → 确保 <inertial> 标签正确定义

验证碰撞形状 → 确保有有效的碰撞几何体

尝试自动估算 → 使用 createMultiBody 手动指定质量

检查加载参数 → 确认未使用 useFixedBase=True 等固定标志

通过系统排查,99%的质量问题都能在URDF文件定义中找到根源。正确配置后,零件将表现出真实的物理行为。