Skip to content

feat(cli): interactive ChArUco camera calibration tool - #16

Draft
TheCrabe wants to merge 6 commits into
mainfrom
feat/calibrate-camera
Draft

feat(cli): interactive ChArUco camera calibration tool#16
TheCrabe wants to merge 6 commits into
mainfrom
feat/calibrate-camera

Conversation

@TheCrabe

@TheCrabe TheCrabe commented May 7, 2026

Copy link
Copy Markdown
Member
  • Adds calibrate-camera CLI: opens a UvcCamera from evo-hl-library, drives a CharucoCalibrationSession interactively (SPACE/c/s/r/q), refuses to save when the gated RMS check fails.
  • Depends on the camera driver work (evolutek/evo-hl-library#feat/driver-camera). Path source on a sibling worktree for local dev.
  • Intended to be run on a dev box with a display or via ssh -X on the robot — not headless.

TheCrabe added 5 commits May 6, 2026 23:47
calibrate-camera CLI drives a UvcCamera + CharucoCalibrationSession from
evo-hl-library, captures views on SPACE, runs the gated calibration on
'c', saves JSON5 on 's'. Adds opencv-python and a path source for the
sibling library worktree.
live (cv2.imshow) requires a display, capture writes raw frames to disk
via pure ssh (with on-demand corner-count feedback), compute runs the
calibration offline on a folder so the RMS threshold can be retuned
without recapturing.
The live mode previously drew only ArUco marker outlines. The user
needed to see whether each frame had enough ChArUco corners (>=10)
before pressing SPACE to capture.

Now interpolateCornersCharuco runs every frame, the resulting corners
are drawn over the preview, and the status overlay shows live/last
counts with a green-vs-orange cue (green when >=10, orange below).

This mirrors the visual feedback of test_aruco/aruco.py used as the
reference prototype.
Allows running calibration on a machine that has cv2 with GUI (laptop)
while the camera lives on a headless host. ustreamer on the robot
exposes the camera as MJPEG over HTTP, the laptop reads it via
cv2.VideoCapture and runs the live preview locally — no X forwarding.

Also fits the case where the local cv2 is opencv-python-headless and
we need to delegate the GUI to a different venv/host.
Adds two GUI subcommands on top of the existing live/capture/compute trio:

- extrinsics: compute (R_robot_camera, t_robot_camera) from a known table
  marker. Live preview locks on a reference tag (auto-detect via
  EUROBOT_FIXED_TABLE_TAGS by default, or explicit --ref-marker-id /
  --marker-table-pos-mm fallback). On SPACE, captures N frames and runs
  bundle PnP global (4N 2D-3D correspondences in one solvePnP ITERATIVE
  with IPPE_SQUARE init) for MLE accuracy under pixel noise. Composes
  T_robot_marker from --robot-table-pos/rot args, calls
  cam.calibrate_extrinsics_from_pose, merges the result into the same
  JSON5 as the intrinsics. Live preview also overlays the marker's RGB
  axes via cv2.drawFrameAxes.

- verify: live readout of every detected ArUco's id, size and 3D
  position in the robot frame. Useful sanity-check after a calibration:
  place a marker at a known robot-frame position, read it back live.
  Per-id size lookup keeps the math correct without --marker-size-mm
  for Eurobot tags.

Renames the original 'live' subcommand to 'intrinsics' for symmetry.

UX hardening applied to all GUI subcommands:
- preview window is resizable and capped at 1280px wide (was rigid
  AUTOSIZE that overflowed 1080p screens)
- Qt platform layer warnings (fonts/xcb) muted via QT_LOGGING_RULES
- explicit \$DISPLAY check at startup with a clear hint to use ssh -X/-Y
@TheCrabe
TheCrabe force-pushed the feat/calibrate-camera branch from 6b688a2 to 102532e Compare May 9, 2026 20:18
Match the lib rename: read t_robot_camera_mm and m.position_robot_mm
instead of the old world-named fields.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant