diff --git a/enclosure/README.md b/enclosure/README.md index 5de1fe7..c12d493 100644 --- a/enclosure/README.md +++ b/enclosure/README.md @@ -44,6 +44,25 @@ Every value marked `MEASURE` in the `.scad` file is an estimate. With calipers, Change a value, then re-export: `openscad -D 'PART="body"' -o stl/body.stl hermes_robot.scad`. +### Regenerating the STLs and the renders + +Checked 2026-10-05 with OpenSCAD 2021.01: every file in `stl/`, `poster/pose/`, `renders/` and the +poster matches the model (same triangles; the two PNGs differ in a handful of anti-aliased pixels). +Without installing anything, via Docker: + +```bash +O="docker run --rm --user $(id -u):$(id -g) -v $PWD:/src -w /src openscad/openscad:2021.01" +$O openscad -D 'PART="body"' -o stl/body.stl hermes_robot.scad # any PART +# PNGs need a virtual display with GLX and software GL; without these flags it hangs +R="docker run --rm --user $(id -u):$(id -g) -v $PWD:/src -w /src -e LIBGL_ALWAYS_SOFTWARE=1 openscad/openscad:2021.01 \ + xvfb-run -a -s '-screen 0 1280x1024x24 +extension GLX' openscad --imgsize=1100,1500 --viewall --autocenter --colorscheme=Tomorrow" +$R -o renders/assembly.png --camera=0,0,0,72,0,-30,500 -D 'PART="assembly"' hermes_robot.scad +$R -o renders/exploded.png --imgsize=1100,1700 --camera=0,0,0,70,0,150,500 -D 'PART="exploded"' hermes_robot.scad +``` + +Known quirk: `back.stl` has two non-manifold edges (four faces meet at one corner, near the +back's rear screw cup); slicers repair it silently. + ## Print the test pieces first | Piece | What it checks | Rough time | diff --git a/enclosure/poster/README.md b/enclosure/poster/README.md index a8fe010..ac695a7 100644 --- a/enclosure/poster/README.md +++ b/enclosure/poster/README.md @@ -11,10 +11,11 @@ cd enclosure for n in base servo_pan plate body yoke servo_tilt cradle camera; do openscad -o poster/pose/$n.stl -D "PART=\"pose_$n\"" -D '$fn=48' hermes_robot.scad done -openscad -o /dev/null -D 'PART="pose_info"' hermes_robot.scad # prints WIN / LED coordinates +openscad -o /tmp/pose_info.stl -D 'PART="pose_info"' hermes_robot.scad # prints WIN / LED coordinates python3 poster/render_poster.py ``` If the window or LED positions change, copy the printed `WIN` and `LED` values into -`render_poster.py`. `face.png` is a frame captured from `docs/face-prototype.html` (flat shape, +`render_poster.py`. The script needs the DejaVu fonts (Debian `fonts-dejavu`, Arch `ttf-dejavu`); elsewhere, set +`POSTER_FONT_DIR` to a folder holding them. `face.png` is a frame captured from `docs/face-prototype.html` (flat shape, P7, speaking). Requires `numpy`, `trimesh` and `Pillow`. diff --git a/enclosure/poster/render_poster.py b/enclosure/poster/render_poster.py index 8664588..fdd4cf0 100644 --- a/enclosure/poster/render_poster.py +++ b/enclosure/poster/render_poster.py @@ -32,10 +32,26 @@ AMBER = np.array([1.00, 0.66, 0.24]) # phosphor / sodium light WARM = np.array([0.95, 0.86, 0.70]) # edge highlight TEAL = np.array([0.30, 0.66, 0.70]) # contours, grid SCREEN = np.array([0.66, 0.82, 1.00]) # P7 phosphor: blue-white -FONT_B = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf" -FONT_L = "/usr/share/fonts/truetype/dejavu/DejaVuSans-ExtraLight.ttf" -FONT_C = "/usr/share/fonts/truetype/dejavu/DejaVuSansCondensed.ttf" -FONT_M = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf" + + +def find_font(name): + """A DejaVu font by file name. Looks in $POSTER_FONT_DIR first, then where Debian/Ubuntu, Arch and + Fedora keep it, so the poster renders on any of them; fails with a clear message otherwise.""" + import os + dirs = [os.environ.get("POSTER_FONT_DIR", ""), "/usr/share/fonts/truetype/dejavu", "/usr/share/fonts/TTF", + "/usr/share/fonts/dejavu", "/usr/share/fonts/dejavu-sans-fonts", "/usr/share/fonts/dejavu-sans-mono-fonts", + os.path.expanduser("~/.local/share/fonts"), os.path.expanduser("~/.fonts")] + for d in dirs: + if d and os.path.isfile(os.path.join(d, name)): + return os.path.join(d, name) + sys.exit(f"render_poster.py needs the DejaVu font {name}. Install DejaVu (Debian: fonts-dejavu, " + f"Arch: ttf-dejavu) or put dejavu-fonts-ttf-2.37/ttf/ somewhere and set POSTER_FONT_DIR to it.") + + +FONT_B = find_font("DejaVuSans-Bold.ttf") +FONT_L = find_font("DejaVuSans-ExtraLight.ttf") +FONT_C = find_font("DejaVuSansCondensed.ttf") +FONT_M = find_font("DejaVuSansMono.ttf") # ------------------------------------------------------------------ camera target = np.array([0.0, 0.0, 112.0])