Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
- Add differentiable rigid contacts (experimental) with respect to body poses via `CollisionPipeline` when `requires_grad=True`
- Add per-shape display colors via `ModelBuilder.shape_color`, `Model.shape_color`, and `color=` on `ModelBuilder.add_shape_*`; mesh shapes fall back to `Mesh.color` when available and viewers honor runtime `Model.shape_color` updates
- Add `ModelBuilder.inertia_tolerance` to configure the eigenvalue positivity and triangle inequality threshold used during inertia correction in `finalize()`
- Add introductory tutorial notebook covering ModelBuilder, solvers, CUDA graphs, IK, and pick-and-place

### Changed

Expand Down Expand Up @@ -63,6 +64,7 @@

### Fixed

- Fix `ViewerViser` notebook playback behind Jupyter proxies by loading the client from the installed `viser` package
- Fix inertia validation spuriously inflating small but physically valid eigenvalues for lightweight components (< ~50 g) by using a relative threshold instead of an absolute 1e-6 cutoff
- Restore keyboard camera movement while hovering gizmos so keyboard controls remain active when the pointer is over gizmos
- Resolve USD asset references recursively in `resolve_usd_from_url` so nested stages are fully downloaded
Expand Down
17 changes: 9 additions & 8 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,21 +395,22 @@ def _copy_viser_client_into_output_static(*, outdir: Path) -> None:
"""Ensure the Viser web client assets are available at `{outdir}/_static/viser/`.

This avoids relying on repo-relative `html_static_path` entries (which can break under `uv`),
and avoids writing generated assets into `docs/_static` in the working tree.
avoids writing generated assets into `docs/_static` in the working tree, and
keeps the copied client aligned with the installed `viser` package.
"""

dest_dir = outdir / "_static" / "viser"

src_candidates: list[Path] = []

# Repo checkout layout (most common for local builds).
src_candidates.append(project_root / "newton" / "_src" / "viewer" / "viser" / "static")

# Installed package layout (e.g. building docs from an environment where `newton` is installed).
# Installed viser package build. Prefer this so the copied docs assets stay in
# sync with the serializer version used for notebook playback.
try:
import newton # noqa: PLC0415
import inspect # noqa: PLC0415

import viser # noqa: PLC0415

src_candidates.append(Path(newton.__file__).resolve().parent / "_src" / "viewer" / "viser" / "static")
src_candidates.append(Path(inspect.getfile(viser)).resolve().parent / "client" / "build")
Comment on lines +406 to +413
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the same static fallback used by ViewerViser.

newton/_src/viewer/viewer_viser.py checks both client/build and static, but this docs-side copy path only registers client/build. If the installed viser package exposes the fallback layout, Sphinx will quietly skip copying the player assets and the embedded notebook replays will end up with a broken ../_static/viser/index.html.

♻️ Proposed fix
     try:
         import inspect  # noqa: PLC0415

         import viser  # noqa: PLC0415

-        src_candidates.append(Path(inspect.getfile(viser)).resolve().parent / "client" / "build")
+        viser_package_dir = Path(inspect.getfile(viser)).resolve().parent
+        src_candidates.extend(
+            [
+                viser_package_dir / "client" / "build",
+                viser_package_dir / "static",
+            ]
+        )
     except Exception:
         pass
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/conf.py` around lines 406 - 413, The docs conf currently only adds the
installed viser package's "client/build" path to src_candidates; update the
block that imports inspect and viser to also append the alternative "static"
fallback used by newton/_src/viewer/viewer_viser.py (i.e., add
Path(inspect.getfile(viser)).resolve().parent / "static") so Sphinx will copy
assets when the package exposes the fallback layout; keep both additions using
the same Path(inspect.getfile(viser)).resolve().parent base and append to
src_candidates like the existing "client/build" entry.

except Exception:
pass

Expand All @@ -418,7 +419,7 @@ def _copy_viser_client_into_output_static(*, outdir: Path) -> None:
# Don't hard-fail doc builds; the viewer docs can still build without the embedded client.
expected = ", ".join(str(p) for p in src_candidates)
print(
f"Warning: could not find Viser client assets to copy. Expected `index.html` under one of: {expected}",
f"Warning: could not find installed Viser client assets to copy. Expected `index.html` under one of: {expected}",
file=sys.stderr,
)
return
Expand Down
Loading
Loading