File size: 3,172 Bytes
7399b6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
"""Copy a SAPIEN articulated asset with USD-legal names, so the URDF importer can read it.

SAPIEN names its collision meshes `original-7.obj`. A hyphen is illegal in a USD prim path, and
Isaac's URDF importer half-handles it: it renames the prim to `original_7` but then still tries
to create `</colliders/base/original-7>`, which fails to parse, and the import dies with
"Used null prim". It writes a 492-byte stub anyway and reports success, so the breakage only
surfaces later as "Failed to find an articulation ... ArticulationRootAPI".

This makes a sanitized copy: hyphens in mesh filenames and in the URDF's references become
underscores. Everything else is untouched.

    python scripts/sanitize_urdf_asset.py 036_cabinet/46653 044_microwave/7310
"""
import os
import re
import shutil
import sys

SRC = os.environ.get("ROBOTWIN_SRC", "/home/yu/internship_yu/robotwin_object/objects")


def sanitize(job):
    cat, inst = job.split("/")
    src = f"{SRC}/{cat}/{inst}"
    dst = f"{SRC}/{cat}/{inst}_clean"
    if not os.path.isdir(src):
        print(f"[san] MISSING {src}")
        return None
    if os.path.isdir(dst):
        shutil.rmtree(dst)
    shutil.copytree(src, dst)

    renamed = 0
    for root, _dirs, files in os.walk(dst):
        for fn in files:
            if "-" in fn:
                os.rename(os.path.join(root, fn), os.path.join(root, fn.replace("-", "_")))
                renamed += 1

    # An OBJ names its material library INSIDE the file (`mtllib original-1.mtl`). Renaming the
    # .mtl on disk without rewriting that line leaves every mesh material-less, and the whole
    # asset imports as featureless grey -- the microwave rendered as a plain cube.
    fixed = 0
    for root, _dirs, files in os.walk(dst):
        for fn in files:
            if not fn.lower().endswith((".obj", ".mtl")):
                continue
            p = os.path.join(root, fn)
            try:
                txt = open(p, errors="ignore").read()
            except OSError:
                continue
            new = re.sub(r'^(mtllib|usemtl|map_Kd|map_Ka|map_Bump|bump)\s+(.+)$',
                         lambda m: f"{m.group(1)} {m.group(2).replace('-', '_')}",
                         txt, flags=re.M)
            if new != txt:
                open(p, "w").write(new)
                fixed += 1

    urdf = os.path.join(dst, "mobility.urdf")
    text = open(urdf).read()
    # only rewrite hyphens inside filename references, not elsewhere in the XML
    text = re.sub(r'(filename\s*=\s*")([^"]+)(")',
                  lambda m: m.group(1)+m.group(2).replace("-", "_")+m.group(3), text)
    # link and joint names feed prim paths too
    text = re.sub(r'((?:link|joint|parent|child)\s+(?:name|link)\s*=\s*")([^"]+)(")',
                  lambda m: m.group(1)+m.group(2).replace("-", "_")+m.group(3), text)
    open(urdf, "w").write(text)
    print(f"[san] {job} -> {cat}/{inst}_clean  ({renamed} files renamed, "
          f"{fixed} mesh files had internal references rewritten)")
    return f"{cat}/{inst}_clean"


if __name__ == "__main__":
    out = [sanitize(j) for j in sys.argv[1:]]
    print("JOBS=" + ",".join(j for j in out if j))