Skip to main content

cdf-simulation

Component-owned guidance for CDF Simulation requests submitted directly or through Airflow-triggered DIG Flow Catalog prompts — golden THT board, THT pin-geometry variation, good/clean SMT images, structural pose defects, and solder texture defects, from a board USD. Turns one matched prompt into one validated `cdf.CDFJob` build and its compiled JobOrder payload; it never executes a render itself. Requires a caller-supplied board USD and output root, asks for either when missing from an interactive request, and resolves optional details with fixed, documented defaults.

Quellinformationen

Repository
NVIDIA/skills
Letzte Quellaktivität
21. Oktober 2026 um 13:43
Erkannte Sprache von SKILL.md
Englisch
Sterne
3.778
Forks
469

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
9 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
cdf-simulation
description
Component-owned guidance for CDF Simulation requests submitted directly or through Airflow-triggered DIG Flow Catalog prompts — golden THT board, THT pin-geometry variation, good/clean SMT images, structural pose defects, and solder texture defects, from a board USD. Turns one matched prompt into one validated `cdf.CDFJob` build and its compiled JobOrder payload; it never executes a render itself. Requires a caller-supplied board USD and output root, asks for either when missing from an interactive request, and resolves optional details with fixed, documented defaults.
license
Apache-2.0
owner
NVIDIA
service
cdf-simulation
metadata
{"version":"1.0.0","author":"NVIDIA CDF <cdf@nvidia.com>","tags":["physical-ai","synthetic-data-generation","simulation","pcba","aoi","airflow"]}
# cdf-simulation Turns DIG Flow Catalog prompt templates and equivalent direct requests into `cdf` jobs through the declarative Python API. This skill is the **component-owned guidance** for `cdf-simulation`: a caller supplies a board USD and output root, this skill builds and compiles the job, and the caller can pass the payload to its own executor. Airflow may inject those required inputs, or the caller may provide them directly. If either is missing and interaction is possible, ask once. All optional ambiguity is resolved with fixed, documented defaults. If a request truly cannot be served (an unsupported defect type, a non-USD input), say so rather than guessing at a fake capability or silently doing nothing. **This skill does not execute.** It produces a validated `CDFJob` build and its compiled JobOrder payload, then stops. An Airflow DAG or another executor chosen by the caller performs rendering. ## Catalog coverage This skill implements five DIG Flow Catalog rows, all taking a board USD as input: | # | Row | Status | |---|---|---| | 1 | Golden board (THT) | Implemented | | 2 | Variation type (THT pin geometry) | Implemented | | 3 | Good images (SMT) | Implemented | | 4 | Structural defects (SMT) | Implemented | | 5 | Texture defects (SMT solder) | Implemented, except `bridge` (unsupported — see below) | ### Reference flows Beside the catalog rows, the skill serves the five **reference flows** in [`references/reference-flows.md`](references/reference-flows.md): complete inspection jobs, each phrased as one prompt whose compiled plan must equal the equivalent YAML config. A prompt carrying a flow marker -- a scan grid and "stitched", a defect on a **named refdes** ("shift on C33", "insufficient solder on J17", "missing-component defect on LS1"), "component-focus" or "pin-focus" crops -- is a flow, not a catalog row, and takes its fixed values from that file (they differ from the catalog defaults: shift is `translate_range=0.5, rotate_z_range=5.0` with no `variant_index`, crops are ROI captures rather than `postprocess.crop`). | Flow | Prompt marker | |---|---| | G golden scan | "golden board dataset ... NxM scan ... stitched" (single board or panel) | | C component defects | "shift/tombstone/sideflip/reverse polarity on <refdes>" + "component-focus crops" | | S SMT solder defects | "insufficient/excess/interrupted/missing solder on <refdes>" + "component-focus crops" | | M missing component | "missing-component defect on <refdes>" | | T THT solder defects | six THT solder defects on refdes + "pin-focus crops from the bottom" (single board or panel) | ## Fixed defaults Every unspecified optional detail resolves to a documented default rather than a question. The full table -- board identity and paths, the rule that a named component must resolve on the attachment, THT board requirements, pin-variation magnitude ranges, **the required structural-defect magnitudes** (`translate_range`, `rotate_z_range`, `angle_range` -- the API has no defaults for these and a catalog prompt never states them), the coverage ratio, how multiple defect types combine, and the solder texture-defect mapping -- is in [`references/fixed-defaults.md`](references/fixed-defaults.md). **Read it before building any script.** The values are not obvious and several of them are load-bearing: the coverage ratio applies to structural *and* solder defects, and the crop `class_filter` taxonomy is not the same as `component_types`. ## Payload contract What this skill returns to its caller, what it accepts, and how each value is validated is in [`references/payload-contract.md`](references/payload-contract.md). The short version: the output is a `CDFJob` build plus the compiled `JobOrderPlan` from `job.compile_orders(...)`, serialized with `JobOrderCodec.dumps(plan)` (a bare `plan.model_dump()` is not JSON-serializable), together with a resolved-inputs summary naming every default that applied. The caller supplies the board USD and output root -- both **required**, with no fallback. This skill supplies everything else from the catalog row and fixed defaults, and marks each variant for an independent process. ## Instructions Four steps, in order. Step 1 decides everything downstream, so do not start writing a script before the row is settled. 1. **Match the prompt to exactly one catalog row or one reference flow.** Check the flow markers first (`references/reference-flows.md`, "Routing"): a named refdes target, a scan grid with "stitched", "component-focus" / "pin-focus" crops. With a marker present the prompt is that flow; without one it is a catalog row. A prompt matching **no row and no flow** explains the supported request shapes and asks the caller to choose one; it never assembles a best-effort substitute out of the pieces that do exist. 2. **Resolve every input from the precedence order in [Inputs](#inputs).** Anything still unset takes its documented default from [`references/fixed-defaults.md`](references/fixed-defaults.md). 3. **Build one `cdf.CDFJob` script**, following the row's shape in [Workflow](#workflow). One job per variant: the executing side must launch each variant as its own process, because sequential `job.capture.render(...)` calls in one process crash the second Kit subprocess -- so the payload says one variant, never a loop. 4. **Validate, then return** -- compile the job with `job.compile_orders(...)`, read the result, and return the build plus the compiled plan to the caller. Do not call `render()` here. Report what was assumed alongside the payload. ## Inputs Each value is resolved from the first source that supplies it: **state file -> explicit prompt arguments -> agent context -> user prompt text** | Input | Required | Where it comes from if unset | |---|---|---| | Catalog row | yes | Matched from the prompt shape; no default. No match asks the caller to choose a supported shape | | Board USD (attachment path) | yes, caller-provided | **No fallback.** Ask for a missing path when interaction is possible; for non-interactive automation, stop with refusal case 3. Never substitute a sample board | | Output root | yes, caller-provided | **No fallback.** Ask for a missing path when interaction is possible; for non-interactive automation, stop with refusal case 3. Never synthesize a directory | | Component sidecar | optional legacy input | Prefer embedded USD metadata with `source="usd"`. Attach a matching `<stem>.components.json` only when a legacy standalone board relies on it or the caller explicitly selects that source; file presence alone does not select it. Instanced panels require embedded metadata | | Board `root_path` | no | Read from the supplied stage, or from the selected legacy sidecar for a sidecar-backed board. For instanced panels follow `references/reference-flows.md`, "Panels". Opening the attachment is required; an unreadable or unresolved board stops with refusal case 3. Never use another board's root as a fallback | | Named component | from the prompt | Passed through as named when present in the selected metadata source (embedded USD by default, or an explicitly selected legacy sidecar -- list types, do not guess); a missing name is refusal case 4, never substituted. State the check in the run summary | | Component types | no | The row's documented set | | Seed, scan grid, board side, resolution, pin numbers (flows) | no | Explicit prompt arguments in the forms listed in `references/reference-flows.md` ("Seed 7", "a 5x4 scan", "of the bottom side", "at 2000x2000", "(pin SH)"); otherwise that file's per-flow defaults | | Panel instances | from the attachment | When the attachment composes one board as several USD instances (`<root>/StepRepeats/SR_*`), register all of them with `job.scene.instances(...)`; image budgets multiply by the instance count (`references/reference-flows.md`, "Panels") | | Coverage ratio | no | The single documented ratio, applied to structural *and* solder defects; the executing side selects `max(1, int(pool * ratio))`, so a non-empty selection always yields at least one defect | | Defect magnitudes | no | The per-type ranges in `references/fixed-defaults.md` | | `class_filter` | no | `None`. Never a component-type string -- different taxonomy | State what was resolved and from where in the run summary so the caller can see which defaults applied. ## Workflow ### 1. Match the prompt to a catalog row Use the sample-prompt phrasing in the table under "Catalog coverage" and in "Examples" below to classify the request into exactly one of rows 1-5. If a prompt does not clearly match any of the rows or a reference flow, explain the supported request shapes and ask the caller to choose one. ### 2. Resolve inputs deterministically Extract from the prompt: attached USD path, output root, named component(s), variation/defect type, "full board coverage" flag. Then **open the attachment** and read two things from it: the board root and its component types, using embedded metadata by default or the selected legacy sidecar for a sidecar-backed standalone board. A named component that appears in those types is used as named; a name that is absent is refusal case 4 -- never a substitution. Apply the fixed defaults above for optional details the prompt does not specify, and record both reads (root source, component check) in the run summary. The attachment path and the output root are the two inputs with **no default**. If either is absent and interaction is possible, ask for it once. For non-interactive automation, stop and report it (refusal case 3). Never substitute a sample board or invent an output directory. Prefer embedded USD metadata. Attach a component sidecar only when a legacy standalone board relies on it or the caller explicitly selects it; do not switch sources merely because a `.components.json` file is nearby. Keep all metadata-dependent calls on that source. Instanced panels cannot use legacy component sidecars. ### 3. Build the `CDFJob` script **`import pcb_aoi` before constructing the job.** The `"pcb-aoi"` domain registers on import; without that import `CDFJob(domain="pcb-aoi", ...)` raises `unknown domain 'pcb-aoi' (registered: none)` on the very first line. Every template below assumes `import pcb_aoi` and `from cdf import CDFJob` at the top of the script. **Every row requires `job.capture.renderer(mode="pathtracing", resolution=..., spp=..., total_spp=..., max_bounces=...)` before `capture.camera`/`scan_grid`/`outputs` -- it is a required field, `compile_orders()` rejects a plan missing it ("capture render pass 'default' is missing: renderer"). Every template below assumes this call is present even where not shown explicitly.** **`capture.camera(rotation_range=...)` is required, not optional** -- only `side=` has a default. A top-side capture with no rotation asked for still needs `rotation_range={"z": 0}`; omitting the kwarg is a `TypeError` before anything is compiled. **Several `operations.add_*` calls have required magnitude kwargs with no defaults** (`add_shift` needs `translate_range` *and* `rotate_z_range`; `add_tombstone` and `add_sideflip` each need `angle_range`). A catalog prompt never states them, so they come from the fixed table in [`references/fixed-defaults.md`](references/fixed-defaults.md) -- do not invent a number and do not ask. **Declaration order matters and is enforced.** `job.scene.select_components(...)` must be declared before `job.annotations.label_components(...)` -- `compile_orders()` rejects the reverse order with `annotations.components.apply requires component selection to be declared first`. Every template below follows select → (operations) → annotate. **`scene.select_components(source=..., types=None)` without `types=` needs either USD-embedded component metadata or `source="components"` pointing at an attached sidecar** -- bare `source="usd"` with no `types` and no sidecar fails at runtime with `component selection needs explicit types or board metadata`. Prefer confirmed embedded USD metadata. For a legacy standalone board that requires a sidecar, attach its matching file with `job.scene.attach_sidecar(name="components", kind="pcb.components", path=...)` and use `source="components"` consistently. Do not mix that source with embedded metadata or attach a sidecar solely because the file exists. Generate a standalone script with imports, `build_job() -> CDFJob`, an `argparse` CLI accepting `--usd-path` and `--output-dir`, and `main()`, using the per-row template below -- or, for a reference flow, the flow's template and shared conventions in `references/reference-flows.md` (explicit `source="usd"`, `output_start(0)`, `limits(...)`, `realtime_subframes=1`, the three-key camera rotation), which are the spellings the YAML interpreter produces. Place generated PCB scripts under `pcb_aoi/examples/` only if the run is meant to be durable/reusable; for a one-off request, build and compile the job in-memory, then emit the payload ([`references/payload-contract.md`](references/payload-contract.md)) without necessarily writing a file to disk. Execution belongs to the caller's chosen executor, never this skill. **Row 1 — Golden board (THT):** the template uses embedded USD metadata. For a legacy sidecar-backed standalone board, attach its matching component sidecar and use its job-local source name consistently instead of `"usd"`. ```python job = CDFJob(domain="pcb-aoi", random_seed=0) job.scene.configure(usd_path=..., root_path=...) # root confirmed on the supplied stage job.scene.select_components(types=[<the attachment's component family>], source="usd") job.appearance.lighting(mode="white_light", exposure_range=(0.0, 0.0), cone_angle_range=(120.0, 120.0), cone_softness_range=(1.0, 1.0), dome={"intensity": (1000.0, 1000.0), "visible": True}) # The catalog's golden board carries PROCEDURAL solder: joints are generated, # no defect is applied. `procedural` is valid here precisely because no # add_* solder-defect call follows (those require surface_evolver). job.operations.solder_joints(solver="procedural", component_types=[<the same family>], source="usd") # component_types names the family the joints are generated for. With a sidecar attached, this reads source="components" too -- all three source= arguments in a row must name the same metadata source job.annotations.label_components(source="usd") # likewise source="components" when the sidecar is attached job.capture.renderer(mode="pathtracing", resolution=(1920, 1080), spp=1, total_spp=32, max_bounces=4) job.capture.camera(side="bottom", rotation_range={"z": -90}) job.capture.scan_grid(x_count=1, y_count=1) job.capture.outputs(rgb=True, bounding_box_2d_tight=True, semantic_segmentation=True, colorize_semantic_segmentation=True) # No postprocess.crop() call -- this row has no crop. ``` `camera_path`/`camera_xform_path`/`ring_light_root` are optional (`scene.configure`'s default is `None`) -- omit them rather than assuming the `/World/camera_light/...` Allegro rig exists verbatim on every board; the pipeline falls back to a synthesized camera when unset. **Row 2 — Variation type (THT pin geometry):** ```python job = CDFJob(domain="pcb-aoi", random_seed=0) job.scene.configure(usd_path=..., root_path=...) # a board that authors pcba:mesh:role -- see below job.appearance.lighting(mode="white_light", exposure_range=(0.0, 0.0), cone_angle_range=(120.0, 120.0), cone_softness_range=(1.0, 1.0), dome={"intensity": (1000.0, 1000.0), "visible": True}) job.operations.pin_variation(components=[<THT refdes>], offset_range=(0.1, 0.4)) # or tilt_range/cut_angle/height_variation job.capture.renderer(mode="pathtracing", resolution=(1920, 1080), spp=1, total_spp=32, max_bounces=4) job.capture.camera(side="bottom", rotation_range={"z": -90}) job.capture.scan_grid(x_count=1, y_count=1) job.capture.outputs(rgb=True) ``` Row 2 needs a board whose through-hole leads are authored with the `pcba:mesh:role` schema (`pkg_lead` meshes); a THT board without it cannot run `pin_variation` at all (see "THT board requirements" in `references/fixed-defaults.md`). `pin_variation(...)` targets leads directly by `components=`/`package_types=` -- it does **not** need `scene.select_components(...)` or `annotations.label_components(...)` declared first (unlike every other row). Selector: the refdes the prompt names, confirmed on the attachment; with no part named, see the selector rule in `references/fixed-defaults.md`. **Row 3 — Good images (SMT):** board-level (`"20 good PCB images"`) uses
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen