User Guide · Asset Library · Onboarding a URDF

Onboarding a URDF

Adding a new articulated object to MetaFine is a deliberate four-step pipeline: drop the URDF in, auto-derive a capabilities file from joint names + a synonym table, run an interactive QA pass, and you're registered. The skill registry picks up the new asset automatically — no re-imports, no per-skill edits.

1 · Drop the URDF in

Create a new directory under assets/ and drop in your urdf.xml + meshes:

assets/my_kettle/
  urdf.xml
  meshes/
    base.obj
    lid.obj
  textures/...

The URDF should already have named links and joints — base, lid, handle, etc. — because the next step uses those names as synonym keys.

2 · Auto-derive capabilities.json

utils.derive_capabilities walks the URDF, inspects each link's joint type (fixed / revolute / prismatic / continuous) and matches the link name against an internal synonym table to seed an initial affordance set per part.

$ python -m utils.derive_capabilities --asset my_kettle

This writes assets/my_kettle/capabilities.json with a best-guess mapping. Example output:

{
  "parts": {
    "base":   ["graspable", "liftable"],
    "lid":    ["graspable", "rotatable", "openable"],
    "handle": ["graspable"]
  },
  "aliases": {
    "cap":    "lid",
    "body":   "base"
  }
}

3 · Interactive QA

utils.review_capabilities is a small interactive shell that walks every part, lets you toggle affordances on / off, add aliases so task-graph YAMLs can refer to parts by friendly names, and confirm the final mapping.

$ python -m utils.review_capabilities --asset my_kettle

# Interactive prompts (illustrative):
part [lid] has affordances: graspable, rotatable, openable
  commands: list / toggle <aff> / alias <name> / walk / confirm
 > toggle insertable
 > alias cap
 > confirm

The walk command pops up a SAPIEN viewer that visually highlights the part being reviewed — invaluable when joint names are cryptic.

4 · Registered automatically

Once capabilities.json is confirmed, the asset is live. The skill registry indexes the asset on next import; every skill whose required affordances are a subset of the asset's offered affordances is now applicable to it.

>>> from core.skill_registry import SKILL_REGISTRY
>>> SKILL_REGISTRY.applicable_skills("my_kettle", part="lid")
['grasp_part', 'pure_rotate', 'lift_lid', 'lid_opening']

From here, drop the asset id into any task-graph YAML and record demos with python record.py.