Calibration Stéréo ================== Matériel nécessaire ------------------- - Damier imprimé **9×6 cases** (intérieur), case **25 mm** - Support rigide (plastifié recommandé) - Éclairage uniforme sans reflets - 2× Microsoft LifeCam HD-3000 sur ``/dev/video0`` (gauche) et ``/dev/video2`` (droite), baseline cible **110 mm** .. warning:: Imprimer sur fond blanc mat. Plastifier sans brillance pour éviter les reflets. Ne pas utiliser d'écran LCD (déformation optique). .. note:: Les HD-3000 ne supportent **pas** le format MJPG. La capture est forcée en **YUYV 640×480 @ 30 fps** (cf. ``cap.set(CAP_PROP_FOURCC, "YUYV")``). La résolution doit être appliquée *après* le fourcc, sinon V4L2 l'ignore. Procédure (issue #1) -------------------- Étape 0 — Déploiement sur le Pi ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash bash scripts/deploy_pi.sh 192.168.0.174 Étape 1 — Capture des paires (sur le Pi, en SSH) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash ssh pi@192.168.0.174 cd ~/slam_stereo # Mode interactif (avec écran X11 forwardé) : python3 src/calibration/stereo_capture.py # OU mode headless (recommandé en SSH, pas d'écran) : python3 src/calibration/stereo_capture.py --headless --count 30 --interval 2.0 - Indices V4L2 par défaut : gauche = ``0``, droite = ``2`` (override : ``--left N --right M``) - Sorties dans ``datasets/calib_raw/`` (gitignored) - Objectif : **≥ 25 paires valides** (varier distance 0.3–1.5 m, inclinaison ±30°, position dans le frame, couvrir les 4 coins + centre) - Alim USB du Pi flaky : éviter les sessions longues, libérer les caméras entre les runs (``cap.release()`` est appelé dans ``finally``). Étape 2 — Calibration (sur le Pi ou rapatrié sur PC) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash python3 src/calibration/stereo_calibrate.py Sortie attendue : .. code-block:: text [INFO] Chargement 30 paires depuis datasets/calib_raw [INFO] Gauche: 28/30 images valides [INFO] Droite: 27/30 images valides [INFO] 26 paires valides pour calibration stéréo [INFO] RMS gauche = 0.31 px [INFO] RMS droite = 0.34 px [INFO] RMS stéréo global = 0.42 px [OK] YAML ORB-SLAM3 → config/stereo_params.yaml [OK] Rapport → config/calibration_report.md [OK] RMS stéréo 0.4200 < 0.5 px ✓ **Gate** : si RMS stéréo > 0.5 px → exit-code 2 (``[STOP]``). Recapturer la mire (mauvais positionnement, flou de bougé, cams sous-focales). Le bypass ``--no-gate`` existe mais ne dispense pas de re-capturer. Livrables (commit après validation) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ``config/stereo_params.yaml`` — format ORB-SLAM3 stéréo (``Camera1.fx``, ``…``, ``Stereo.T_c1_c2``, ``Stereo.bf``, ``IMU.T_b_c1``…) - ``config/calibration_report.md`` — RMS per-cam + RMS stéréo + baseline mesurée Format YAML ORB-SLAM3 généré ---------------------------- .. code-block:: yaml %YAML:1.0 File.version: "1.0" Camera.type: "PinHole" Camera1.fx: 525.123 # cam gauche Camera1.fy: 524.987 Camera1.cx: 319.876 Camera1.cy: 239.234 Camera1.k1: -0.05432 # distorsion Plumb-Bob (4 coefs) Camera1.k2: 0.00821 Camera1.p1: 0.00012 Camera1.p2: -0.00045 Camera2.fx: 525.456 # cam droite # … Camera.width: 640 Camera.height: 480 Camera.fps: 30 Stereo.T_c1_c2: !!opencv-matrix # transfo cam_droite → cam_gauche rows: 4 cols: 4 dt: f data: [...] Stereo.b: 0.110000 # baseline (m) Stereo.bf: 57.7600 # baseline * fx Stereo.ThDepth: 40.0 IMU.T_b_c1: !!opencv-matrix # placeholder identité rows: 4 cols: 4 dt: f data: [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1] Validation ---------- 1. Erreur RMS stéréo **< 0.5 px** (gate strict, issue #1) 2. Lignes épipolaires horizontales sur image rectifiée (``python3 src/calibration/stereo_calibrate.py --show-rectified``) 3. Translation ``T ≈ [-0.110, 0, 0]`` m (baseline sur axe X) 4. Épipole à l'infini après rectification (caméras parallèles) Références ---------- :cite:`bradski2008learning` — OpenCV stereoCalibrate, stereoRectify. :cite:`ferrera2019underwater` — Prise en compte réfraction eau/verre.