chore(release): v0.1.1 USD文件初步校验
原因:记录 L20 USD 初步校验、严格浮动覆盖层、受限动力学回放及 HDF5 交付契约,包版本更新为 0.1.1。 验证:68 项 CPU/USD 回归测试通过,Ruff/format 与暂存 diff 检查通过;已核验单环境 small 2x480、合成 HDF5 2x960 步明确 PASS。独立暂存审查未发现问题。完整 pre-commit 因模块缺失未执行,干净环境安装未验证。 兼容性:Cartpole 及任务 ID 不变,原始 USD/URDF 未改;旧 prepared 覆盖层需重新生成。仅合成轨迹初步校验,不代表真实专家回放、训练或硬件验收。
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""Isaac Lab scene-loading diagnostic ONLY: no physics steps, actuators, or replay.
|
||||
|
||||
Run headless with an external timeout. This legacy topology diagnostic deliberately
|
||||
performs no dynamic experiment (see track_l20.py for the experimental path). Create a disposable
|
||||
floating overlay first; this script never edits/saves USD layers or existing scenes.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import random
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main():
|
||||
from isaaclab.app import AppLauncher
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("asset", type=Path, help="Diagnostic floating overlay, not the fixed preview")
|
||||
AppLauncher.add_app_launcher_args(parser)
|
||||
parser.set_defaults(headless=True)
|
||||
args = parser.parse_args()
|
||||
asset = args.asset.resolve(strict=True)
|
||||
|
||||
# USD inspection imports pxr: defer it until Kit has initialized its libraries.
|
||||
launcher = AppLauncher(args)
|
||||
app = launcher.app
|
||||
exit_code = 0
|
||||
try:
|
||||
import numpy as np
|
||||
import torch
|
||||
from dex_workbench_tracking.asset import inspect
|
||||
|
||||
manifest = inspect(asset)
|
||||
if manifest["world_fixed_joints"] or manifest["articulation_roots"] != [manifest["root_body_path"]]:
|
||||
parser.error("Expected a floating diagnostic overlay; use dex_workbench_tracking.asset first")
|
||||
|
||||
from pxr import UsdGeom, UsdPhysics
|
||||
|
||||
import isaaclab.sim as sim_utils
|
||||
|
||||
random.seed(42)
|
||||
np.random.seed(42)
|
||||
torch.manual_seed(42)
|
||||
sim = sim_utils.SimulationContext(sim_utils.SimulationCfg(dt=1 / 240, device=args.device))
|
||||
spawn = sim_utils.UsdFileCfg(usd_path=str(asset))
|
||||
spawn.func("/World/Hand", spawn)
|
||||
stage = sim.stage
|
||||
roots, joint_names = [], []
|
||||
for prim in stage.Traverse():
|
||||
if not str(prim.GetPath()).startswith("/World/Hand/"):
|
||||
continue
|
||||
if prim.HasAPI(UsdPhysics.ArticulationRootAPI):
|
||||
roots.append(str(prim.GetPath()))
|
||||
if prim.IsA(UsdPhysics.RevoluteJoint):
|
||||
joint_names.append(prim.GetName())
|
||||
if prim.HasAPI(UsdPhysics.RigidBodyAPI):
|
||||
matrix = UsdGeom.XformCache().GetLocalToWorldTransform(prim)
|
||||
if not np.isfinite(np.asarray(matrix)).all():
|
||||
raise AssertionError(f"Nonfinite initial body transform: {prim.GetPath()}")
|
||||
expected = "/World/Hand" + manifest["root_body_path"][len(manifest["default_prim"]) :]
|
||||
assert roots == [expected], (roots, expected)
|
||||
assert sorted(joint_names) == [joint["name"] for joint in manifest["joints"]]
|
||||
assert not stage.GetCompositionErrors(), stage.GetCompositionErrors()
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"status": "PASS",
|
||||
"check": "Isaac_Lab_scene_loading_only",
|
||||
"seed": 42,
|
||||
"num_envs": 1,
|
||||
"physics_steps": 0,
|
||||
"root": expected,
|
||||
"joints": len(joint_names),
|
||||
"dynamic_replay": "BLOCKED",
|
||||
"reset_and_tracking_metrics": "NOT_RUN",
|
||||
}
|
||||
),
|
||||
flush=True,
|
||||
)
|
||||
except BaseException:
|
||||
exit_code = 1
|
||||
traceback.print_exc()
|
||||
raise
|
||||
finally:
|
||||
# No SimulationContext.reset()/step(): even passive dynamics are unvalidated.
|
||||
app.close(exit_code=exit_code)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user