Skip to content

Commit b4b9864

Browse files
committed
usdGeospatial: README voice pass — cut changelog/dev-journal framing
Register-only pass (no re-structure, no facts changed): strip implementation-history narration a reviewer never needs while keeping every caveat as a present-tense property of the design. - Proof 4: drop the SetStage-fallback aside ('stage-free path added alongside the SetStage path, preserved as fallback'); state the thread-safety as a present-tense fact (mutex-guarded XformCache) instead of 'getting Storm to render surfaced a bug'. - Projected-vs-geographic rule: rewrite 'an earlier revision used the ENU lift ... the harness caught it' as a present-tense property (compose through true-ENU instead of the grid plane -> 4.86 m off; the test asserts frame selection). Same fact, no changelog. - Guard rails / open questions: 'the adversarial testing surfaced' -> present tense; drop 'now'/'no longer' temporal phrasing. - Running: drop the 'Tier 1/Tier 2' plan-numbering labels (keep both run modes). - Status: 'Done:' checklist -> 'It demonstrates:' present-tense properties. All numbers/proofs/caveats preserved (418.9m/4.86m/6,369km/162mm/480,000x/ 0.40mm/0.0mm/NCAT/DB no-overfit/thread-safety/9-9/30-30/5-CRS anti-overfit/ composition-overlay). Deck re-derived (26 slides, unchanged; markers untouched). PR body kept in sync (same SetStage->'no application code' edit); all 8 README anchors verified against current slugs.
1 parent e58e3c0 commit b4b9864

2 files changed

Lines changed: 28 additions & 27 deletions

File tree

extras/usd/examples/usdGeospatial/README.md

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -107,25 +107,24 @@ the build if disagreement exceeds 1 mm**.
107107
![Python vs Hydra transforms, same stage (Matplotlib plot)](docs/runtime_parity.png)
108108

109109
**4 — It just works in usdview (real Hydra Storm render).** Beyond the plots: with only the built
110-
plugins on `PXR_PLUGINPATH_NAME`**no `SetStage`, no hand-built scene-index chain, no app
111-
edits**opening the georef scene in **usdview** (or `usdrecord`) draws the railway at its correct
110+
plugins on `PXR_PLUGINPATH_NAME`**no application code, no hand-built scene-index chain**
111+
opening the georef scene in **usdview** (or `usdrecord`) draws the railway at its correct
112112
ECEF position via Storm. The `crs:` data flows through Hydra and an auto-inserted scene index
113113
resolves it. This is a *real renderer image*, not a plot.
114114

115115
<!-- slide:image src="docs/railway_storm_autoinsert.png" eyebrow="Proof · real render, auto-insert" title="It just works in usdview (Storm)" caption="Real Hydra Storm render (not a plot): with the plugin on the path, the railway auto-resolves at its ECEF position — no app code. Negative control (plugin removed): railway absent. The auto-insert path matches the oracle 30/30 at 0.0 mm (testHydraAutoParity)." -->
116116

117117
![usdview Storm auto-insert render (real render)](docs/railway_storm_autoinsert.png)
118118

119-
How it works: `crs:` properties are custom attrs/rel on a codeless schema, so they never entered
119+
How it works: `crs:` properties are custom attrs/rel on a codeless schema, so they are absent from
120120
the default Hydra stream. A **keyless `UsdImagingAPISchemaAdapter`** (`apiSchemaName ""`, modeled on
121121
`coordSysAPIAdapter` and NVIDIA's `omniGeoSceneIndex`) surfaces `crs:position`/`crs:binding`/
122-
`crs:wkt` *into* Hydra for every prim; the scene index then resolves entirely from the Hydra data
123-
stream (a stage-free path added alongside the `SetStage` path, which is preserved as fallback).
124-
*Scope note (stated, not hidden):* the auto path resolves **direct** `crs:binding` (+ nearest /
125-
stronger); collection- and purpose-based strength remain stage-path only — the neutral railway /
126-
earth2 scenes use direct bindings, which is what auto-insert exercises. (Getting Storm to render also
127-
surfaced and fixed a real bug: the resolver's `UsdGeomXformCache` was not thread-safe, and Storm syncs
128-
rprims across TBB threads — a double-free — now guarded by a mutex.)
122+
`crs:wkt` *into* Hydra for every prim; the scene index resolves entirely from the Hydra data
123+
stream. *Scope note (stated, not hidden):* the auto path resolves **direct** `crs:binding`
124+
(+ nearest / stronger); collection- and purpose-based strength are resolved via the stage path — the
125+
neutral railway / earth2 scenes use direct bindings, which is what auto-insert exercises. The resolver
126+
is thread-safe: its `UsdGeomXformCache` is mutex-guarded, so Storm can sync rprims across TBB threads
127+
without a double-free.
129128

130129
## The design call: resolve, don't bake
131130

@@ -225,12 +224,13 @@ goes wrong: **compose a child's offsets in the frame its anchor's CRS implies.**
225224
anchor→corner lever in a UTM-17N-under-UTM-30N test).
226225

227226
The authored scene is identical either way; the runtime selects the frame from the bound CRS type
228-
(`crs_engine.is_projected`). This rule was **found by an adversarial head-to-head**
229-
(`test_coexist_vs_baked.py`) that rebuilds Simon Haegler's multi-CRS POC scene (MoMA in
227+
(`crs_engine.is_projected`). An adversarial head-to-head enforces this rule
228+
(`test_coexist_vs_baked.py`): it rebuilds Simon Haegler's multi-CRS POC scene (MoMA in
230229
NAD83/UTM-17N under a WGS84/UTM-30N anchor) both baked and neutral and measures each against an
231-
independent closed-form pyproj ground truth. Both approaches now land the corner at the same ECEF
232-
point to **0.0 mm**; an earlier revision that used the ENU lift for the projected anchor landed
233-
4.86 m off, and the harness caught it.
230+
independent closed-form pyproj ground truth. Composed in the CRS-implied frame, both approaches land
231+
the corner at the same ECEF point to **0.0 mm**; compose a projected anchor's child through the
232+
true-ENU basis instead of its grid plane and the corner lands 4.86 m off — the test asserts the
233+
frame selection so that error cannot pass silently.
234234

235235
## Non-geometric georeferenced data — visualize by composition, don't bake
236236

@@ -306,7 +306,7 @@ renders empty, so the placement is unambiguously the runtime's, not the geometry
306306
<!-- slide:section title="Guard rails" subtitle="Coexist's costs are asset-structure invariants a validator can enforce." -->
307307
<!-- slide:text eyebrow="Enforceable, not showstoppers" title="Guard rails a validator can check" body="Coexist has no architectural showstopper — it matches baking to 0 mm when it composes in the CRS-implied frame. | Its residual costs are a small set of ASSET-STRUCTURE invariants, each mechanically checkable. | (1) anchor-vs-child is unambiguous; (2) child offsets are authored in the frame the bound CRS implies; (3) a CRS-requiring stage declares it so unaware consumers detect-and-refuse. | A neutral authored scene PRESERVES the semantic info a validator needs; a baked scene has already collapsed CRS intent into a matrix." -->
308308

309-
The adversarial testing surfaced the honest shape of "coexist": it is **not** blocked by any
309+
The honest shape of "coexist" is that it is **not** blocked by any
310310
architectural showstopper — it reproduces the baked approach to 0.0 mm when it composes in the
311311
CRS-implied frame. Its residual costs are a small set of **asset-structure invariants**, and the
312312
important property is that **each is mechanically checkable by a validator** — the same conformance
@@ -444,9 +444,9 @@ Every test is openable and runnable; each has a real negative control or an inde
444444
puts georef prims at the origin. `testHydraAutoParity` adds the stage-free auto-insert path (30/30).
445445
- `pxr/usd/usdGeospatial/regen-schema.sh --check` — schema resources are in sync.
446446

447-
### Running — two honest tiers
447+
### Running — two paths
448448

449-
**Tier 1 — the codeless Python path (no external renderer):**
449+
**The codeless Python path (no external renderer):**
450450

451451
```bash
452452
source <repo>/.venv/bin/activate # usd-core 26.5, pyproj 3.7.1 (PROJ 9.5.1)
@@ -460,10 +460,10 @@ python3 src/render_figures.py # regenerate the Python-reference figure
460460
```
461461

462462
`render_figures.py` regenerates the nine Python-reference figures; it also produces
463-
`multi_runtime.png` / `runtime_parity.png` **if** the compiled C++ Hydra binary is already built
464-
(Tier 2), otherwise it skips those two with a clear note.
463+
`multi_runtime.png` / `runtime_parity.png` **if** the compiled C++ Hydra binary is already built,
464+
otherwise it skips those two with a clear note.
465465

466-
**Tier 2 — the full two-runtime parity proof (needs a prebuilt USD):**
466+
**The full two-runtime parity proof (needs a prebuilt USD):**
467467

468468
```bash
469469
USD_INST=/path/to/usd/inst ../usdGeospatialSceneIndex/run_parity.sh
@@ -480,10 +480,11 @@ notes for reproducing the auto-insert usdview / usdrecord render.
480480
reference runtime and a compiled C++ Hydra scene-index runtime (an illustrative consumer, modeled on
481481
the Gaussian-splat example — not a prescribed production renderer). The Esri C++ typed schema
482482
remains the parallel artifact; this bundle backs the proposal's design calls (binding shape, no
483-
baked `resetXformStack`, resolution-rule parity) with running code on a real dataset. **Done:**
484-
anchor injection (the coexist answer); the head-to-head vs the baked approach (neutral reproduces it
485-
to 0.0 mm, hand-TRS edits survive, neutral resolve cost ~1.8 ms/prim); the compiled Hydra
486-
scene-index form with auto-insert into usdview; the projection-engine seam.
483+
baked `resetXformStack`, resolution-rule parity) with running code on a real dataset. It
484+
demonstrates: anchor injection (the coexist answer); a head-to-head against the baked approach in
485+
which neutral reproduces it to 0.0 mm, hand-TRS edits survive, and neutral resolve costs
486+
~1.8 ms/prim; the compiled Hydra scene-index form with auto-insert into usdview; and the
487+
projection-engine seam.
487488

488489
**Out of scope here (need other resources):** a codeless `usdchecker`-discoverable validator plugin
489490
(`verify.py` is the runnable validator today); a draped raster / terrain basemap for the coherence
@@ -500,8 +501,8 @@ read on:
500501
conformance suite, prose in the spec)?
501502
2. **Is "coexist" the right relationship to `UsdGeomXformable`** — a coordinate-neutral authored
502503
scene plus runtime reconciliation — versus hooking CRS resolution into `Xformable` directly? The
503-
head-to-head now shows neutral **reproduces the baked approach to 0.0 mm** on a real multi-CRS
504-
scene, so the question is no longer "does coexist work?" but **"is the residual guard-rail set
504+
head-to-head shows neutral **reproduces the baked approach to 0.0 mm** on a real multi-CRS
505+
scene, so the question is not "does coexist work?" but **"is the residual guard-rail set
505506
(anchor-vs-child, compose-in-CRS-frame, requires-CRS marker) an acceptable conformance surface to
506507
standardize?"**
507508

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)