docs: Sphinx — 9 pages rst, conf.py rtd-theme, sources.bib, navigator_imu

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Floppyrj45
2026-04-19 18:07:05 +02:00
parent c14fdfe572
commit 9a46824199
13 changed files with 861 additions and 0 deletions

106
docs/source/blueos.rst Normal file
View File

@@ -0,0 +1,106 @@
Intégration BlueOS
==================
BlueOS Overview
---------------
BlueOS est le système d'exploitation embarqué de Blue Robotics
pour le BlueROV2. Il tourne sous Raspberry Pi OS + Docker.
Les extensions BlueOS sont des conteneurs Docker exposés via
une API REST et une UI web intégrée.
Extension SLAM
--------------
L'extension SLAM est définie dans ``/Dockerfile`` à la racine du projet.
Format manifest BlueOS
~~~~~~~~~~~~~~~~~~~~~~~
Chaque extension doit inclure des labels Docker spécifiques :
.. code-block:: dockerfile
LABEL version="0.1.0"
LABEL permissions='{"NetworkMode": "host", "Devices": ["/dev/video0", "/dev/video1"]}'
LABEL authors='[{"name": "Baptiste Moulin", "email": "baptiste@example.com"}]'
LABEL company='{"about": "", "name": "Baptiste Moulin", "email": ""}'
LABEL type="device-integration"
LABEL tags='["slam", "stereo", "vision"]'
LABEL readme='https://raw.githubusercontent.com/.../README.md'
LABEL links='{"website": "", "support": ""}'
Accès caméras USB
~~~~~~~~~~~~~~~~~
BlueOS utilise ``udev`` pour les caméras. S'assurer que :
.. code-block:: bash
# Sur le Pi, vérifier les devices
ls /dev/video*
# → /dev/video0 /dev/video1
# Dans BlueOS Docker, les devices sont passés via permissions JSON
# "Devices": ["/dev/video0", "/dev/video1"]
Port réseau
~~~~~~~~~~~
L'interface Flask tourne sur le port **5000**.
BlueOS expose les extensions via son proxy Nginx.
Accès depuis l'interface BlueOS : ``http://<IP_PI>/extensions/slam-stereo``.
Installation via BlueOS UI
--------------------------
1. Ouvrir BlueOS : ``http://<IP_PI>``
2. Menu → Extensions → Installer
3. Entrer l'image Docker : ``ghcr.io/baptiste-moulin/slam-stereo-blueos:latest``
4. Valider les permissions
5. Lancer l'extension
Installation manuelle (SSH)
----------------------------
.. code-block:: bash
ssh pi@<IP_PI>
# Build l'image localement
cd /home/pi/slam_stereo
docker build -t slam-stereo-blueos .
# Lancer le conteneur
docker run -d \
--network host \
--device /dev/video0 \
--device /dev/video1 \
-p 5000:5000 \
--name slam-stereo \
slam-stereo-blueos
Logs
----
.. code-block:: bash
docker logs -f slam-stereo
MAVLink Integration (optionnel)
---------------------------------
Pour envoyer la pose estimée au pilote automatique (ArduSub/ArduPilot) :
- Protocole MAVLink ``VISION_POSITION_ESTIMATE`` (ID 102)
- Bibliothèque Python : ``pymavlink``
- Connexion via ``udpin:0.0.0.0:14550`` (BlueOS MAVLink router)
.. code-block:: python
# Exemple envoi pose (à implémenter dans src/slam/mavlink_bridge.py)
from pymavlink import mavutil
mav = mavutil.mavlink_connection('udpout:127.0.0.1:14550')
mav.mav.vision_position_estimate_send(
usec, x, y, z, roll, pitch, yaw
)

101
docs/source/calibration.rst Normal file
View File

@@ -0,0 +1,101 @@
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
.. warning::
Imprimer sur fond blanc mat. Plastifier sans brillance pour éviter
les reflets. Ne pas utiliser d'écran LCD (déformation optique).
Procédure
---------
Étape 1 — Capture des paires
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
python src/calibration/stereo_capture.py
- Lance les 2 webcams simultanément (USB 0 et 1)
- Appuyer sur ``ESPACE`` pour capturer une paire
- Objectif : **30 paires valides** minimum
- Varier : distance (0.31.5 m), inclinaison (±30°), position dans frame
.. tip::
Couvrir les 4 coins du champ + centre. Inclure des poses inclinées
pour mieux contraindre les coefficients de distorsion tangentielle.
Étape 2 — Calibration
~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: bash
python src/calibration/stereo_calibrate.py
Résultat attendu :
.. code-block:: text
Chargement 30 paires de damier...
Calibration stéréo...
RMS reprojection error: 0.42 px ← bon si < 0.8 px
Sauvegarde: config/stereo_calib.yaml
Fichier YAML généré
-------------------
``config/stereo_calib.yaml`` contient :
.. code-block:: yaml
K1: [[fx, 0, cx], [0, fy, cy], [0, 0, 1]] # caméra gauche
D1: [k1, k2, p1, p2, k3] # distorsion gauche
K2: [[fx, 0, cx], [0, fy, cy], [0, 0, 1]] # caméra droite
D2: [k1, k2, p1, p2, k3] # distorsion droite
R: [[...], [...], [...]] # rotation C2→C1
T: [tx, ty, tz] # translation (baseline)
E: [[...]] # matrice essentielle
F: [[...]] # matrice fondamentale
R1, P1, R2, P2, Q # rectification
Paramètres OpenCV
-----------------
``stereoCalibrate`` avec flags :
.. code-block:: python
flags = (
cv2.CALIB_FIX_INTRINSIC # si calibration individuelle faite avant
# ou cv2.CALIB_RATIONAL_MODEL # pour modèle 8 coefs
)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-5)
``stereoRectify`` avec ``alpha=0`` (recadrage maximal, pas de bandes noires).
Validation
----------
Après calibration, vérifier :
1. Erreur RMS < 0.8 px (idéalement < 0.5 px)
2. Lignes épipolaires horizontales sur image rectifiée
3. Translation T ≈ [0.11, 0, 0] m (baseline sur axe X)
4. Épipole à l'infini (caméras parallèles après rectif)
.. code-block:: bash
# Visualisation rectification
python src/calibration/stereo_calibrate.py --show-rectified
Références
----------
:cite:`bradski2008learning` — OpenCV stereoCalibrate, stereoRectify.
:cite:`ferrera2019underwater` — Prise en compte réfraction eau/verre.

38
docs/source/conf.py Normal file
View File

@@ -0,0 +1,38 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'SLAM_Stereo_BlueOS'
copyright = '2026, Baptiste Moulin'
author = 'Baptiste Moulin'
version = '0.1'
release = '0.1'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'sphinx.ext.mathjax',
'myst_parser',
'sphinxcontrib.bibtex',
]
templates_path = ['_templates']
exclude_patterns = []
# BibTeX
bibtex_bibfiles = ['sources.bib']
# MyST
myst_enable_extensions = ['dollarmath', 'amsmath']
# -- Options for HTML output -------------------------------------------------
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']

View File

@@ -0,0 +1,98 @@
Déploiement — Raspberry Pi
==========================
Prérequis
---------
- ``sshpass`` installé (``sudo apt install sshpass`` ou ``brew install sshpass``)
- ``rsync`` disponible
- Pi accessible via réseau (BlueOS Ethernet ou WiFi)
- Credentials par défaut : ``pi`` / ``raspberry``
Script deploy
-------------
.. code-block:: bash
bash scripts/deploy_pi.sh <IP_DU_PI>
# Exemple :
bash scripts/deploy_pi.sh 192.168.2.2
Le script effectue :
1. Test de connectivité SSH
2. ``rsync`` de ``/src/`` vers ``/home/pi/slam_stereo/src/``
3. ``rsync`` de ``/config/`` vers ``/home/pi/slam_stereo/config/``
4. Installation pip des dépendances Python
5. Redémarrage du service Flask (si systemd configuré)
Installation manuelle
---------------------
.. code-block:: bash
ssh pi@<IP_PI>
# Installer dépendances système
sudo apt update
sudo apt install -y python3-pip python3-opencv libopencv-dev
# Installer dépendances Python
pip3 install flask numpy pyyaml opencv-python
# Copier les fichiers (depuis PC)
rsync -av src/ pi@<IP_PI>:/home/pi/slam_stereo/src/
rsync -av config/ pi@<IP_PI>:/home/pi/slam_stereo/config/
Service systemd (optionnel)
-----------------------------
Créer ``/etc/systemd/system/slam-stereo.service`` sur le Pi :
.. code-block:: ini
[Unit]
Description=SLAM Stereo Flask Interface
After=network.target
[Service]
User=pi
WorkingDirectory=/home/pi/slam_stereo
ExecStart=/usr/bin/python3 src/interface/app.py
Restart=always
[Install]
WantedBy=multi-user.target
.. code-block:: bash
sudo systemctl enable slam-stereo
sudo systemctl start slam-stereo
Vérification
------------
.. code-block:: bash
# Depuis le Pi
curl http://localhost:5000/
# Depuis le réseau
curl http://<IP_PI>:5000/
# Logs Flask
journalctl -u slam-stereo -f
Notes BlueOS
------------
BlueOS expose le Pi sur ``192.168.2.2`` par défaut (connexion USB-Ethernet).
En WiFi, l'IP est assignée par DHCP.
Pour trouver l'IP :
.. code-block:: bash
# Depuis BlueOS web UI : Settings → Network
# Ou scan réseau :
nmap -sn 192.168.2.0/24

74
docs/source/hardware.rst Normal file
View File

@@ -0,0 +1,74 @@
Hardware
========
Composants
----------
Raspberry Pi 4B
~~~~~~~~~~~~~~~
- **CPU** : Broadcom BCM2711, Cortex-A72 64-bit @ 1.8 GHz
- **RAM** : 4 GB LPDDR4
- **OS** : BlueOS (Raspbian Bullseye + Docker)
- **Connexion** : Ethernet ou WiFi 5 GHz
- **Alimentation** : 5V 3A via câble BlueROV2 ou USB-C
Caméras stéréo — Microsoft LifeCam HD-3000
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- **Résolution** : 1280×720 @ 30 fps
- **Interface** : USB 2.0
- **Focale estimée** : ~525 px (à calibrer)
- **Champ** : ~68° horizontal
- **Boîtier** : étanche DIY ou logement BlueROV2
.. note::
Les caméras ne sont pas étanches nativement. Un boîtier optique
plat (port verre optique sans distorsion) est nécessaire.
Utiliser du verre borosilicate 5 mm, joint EPDM, serrage 6 vis M3.
Carte Navigator (Blue Robotics)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
La carte Navigator est directement connectée au GPIO 40-pins du Pi4B.
- **IMU** : Bosch BMI088 (accéléromètre + gyroscope 6-axes séparés)
- **Baromètre/profondimètre** : TE MS5837-30BA (0300 bar)
- **PWM thrusters** : NXP PCA9685 (16 canaux I2C)
- **Interface** : SPI (BMI088) + I2C (MS5837, PCA9685)
- **Fréquence IMU** : jusqu'à 400 Hz configurable via ArduSub
- Voir ``docs/source/navigator_imu.rst`` pour détail fusion VIO
Support caméras (OpenSCAD)
~~~~~~~~~~~~~~~~~~~~~~~~~~
Voir ``/hardware/camera_mount.scad``.
- Espacement fixe **11 cm** (médiane de la plage optimale 1012 cm)
- Trous M3 × 4 pour fixation sur châssis AUV
- Slot câbles USB intégré
- Matériau recommandé : PETG (résistance eau, déformation thermique)
Montage
-------
::
Vue de dessus :
USB-A Pi4 USB-A Pi4
| |
________↓_________ _________↓________
| LifeCam gauche |←11cm→| LifeCam droite |
|__________________| |__________________|
↓ ↓
Cam 0 Cam 1
(cv2.VideoCapture(0)) (cv2.VideoCapture(1))
Connectique BlueROV2
--------------------
Le Raspberry Pi 4B se loge dans le tube électronique principal.
Les câbles USB traversent le presse-étoupe 4 trous M10.
Prévoir longueur câble USB ≥ 30 cm (interne) + 15 cm (externe vers support).

24
docs/source/index.rst Normal file
View File

@@ -0,0 +1,24 @@
SLAM Stéréo BlueOS — Documentation
====================================
SLAM visuel stéréo pour AUV sous-marin autonome.
Intégration BlueOS (Raspberry Pi 4B), ORB-SLAM3, Flask.
.. toctree::
:maxdepth: 2
:caption: Contenu
hardware
theory_baseline
calibration
navigator_imu
slam_stack
blueos
deployment
sources
Indices et tables
==================
* :ref:`genindex`
* :ref:`search`

View File

@@ -0,0 +1,68 @@
Carte Navigator — BMI088 IMU
=============================
La carte Navigator de Blue Robotics embarque :
- **IMU** : Bosch BMI088 (accéléromètre 6-axes + gyroscope 6-axes, séparés physiquement)
- **Baromètre** : TE MS5837-30BA (profondimètre 300 bar)
- **PWM** : NXP PCA9685 (16 canaux, contrôle thrusters via ArduSub)
Spécifications BMI088
---------------------
.. list-table::
:header-rows: 1
* - Paramètre
- Valeur
* - Plage accéléromètre
- ±3g / ±6g / ±12g / ±24g
* - Bruit accéléromètre
- 175 μg/√Hz
* - Plage gyroscope
- ±125 à ±2000 °/s
* - Bruit gyroscope
- 0.014 °/s/√Hz
* - Interface
- SPI / I2C
* - Fréquence sortie
- 100400 Hz (configurable)
Accès via BlueOS / MAVLink
---------------------------
ArduSub lit le BMI088 via l'interface SPI interne de la Navigator.
Les données IMU sont accessibles en MAVLink (message ``SCALED_IMU``).
.. code-block:: python
from pymavlink import mavutil
mav = mavutil.mavlink_connection('udpin:192.168.0.174:14550')
mav.wait_heartbeat()
while True:
msg = mav.recv_match(type='SCALED_IMU', blocking=True)
if msg:
ax = msg.xacc / 1000.0 # mg -> g
ay = msg.yacc / 1000.0
az = msg.zacc / 1000.0
gx = msg.xgyro / 1000.0 # mrad/s -> rad/s
print(f"Acc: {ax:.3f} {ay:.3f} {az:.3f} g")
Fusion visuo-inertielle (VIO)
------------------------------
ORB-SLAM3 mode **Stereo-Inertial** requiert :
1. Extrinsèques IMU-caméra (matrice ``T_cam_imu``) — à calibrer via Kalibr
2. Biais accéléromètre et gyroscope (InitialAccBias, InitialGyroBias)
3. Fréquence IMU ≥ 200 Hz (configurer ArduSub ``IMU_FAST_RATE=1``)
Fichier config ORB-SLAM3 : ``config/navigator_imu.yaml`` (à générer après calibration Kalibr).
Références
----------
- `Blue Robotics Navigator Documentation <https://bluerobotics.com/store/electronics/navigator/>`_
- BMI088 Datasheet — Bosch Sensortec BST-BMI088-DS001

134
docs/source/slam_stack.rst Normal file
View File

@@ -0,0 +1,134 @@
Stack SLAM
==========
Choix : ORB-SLAM3
-----------------
ORB-SLAM3 :cite:`campos2021orbslam3` est retenu comme backend SLAM.
Justification :
- **Modes** : Monoculaire, Stéréo, RGB-D, IMU (Stéréo-Inertiel)
- **Précision** : RMSE trajectoire < 2 cm en stéréo indoor (EuRoC dataset)
- **Open-source** : GPLv3, actif sur GitHub
- **ROS2** : wrappers disponibles (ros2-orbslam3)
- **Robustesse** : réinitialisation automatique, loop closure, multi-map
Comparatif
----------
.. list-table::
:header-rows: 1
:widths: 20 20 20 20 20
* - Stack
- Mode stéréo
- IMU
- ROS2
- Licence
* - **ORB-SLAM3**
- Oui
- Oui
- Via wrapper
- GPLv3
* - VINS-Fusion
- Oui
- Oui
- ROS1 natif
- GPLv3
* - OpenVSLAM
- Oui
- Non
- Oui
- BSD
* - Kimera
- Oui
- Oui
- ROS1
- BSD
* - ElasticFusion
- RGB-D only
- Non
- Non
- Non-commercial
VINS-Fusion :cite:`qin2019fusion` — candidat secondaire.
Avantage : robustesse outdoor. Inconvénient : ROS1, moins maintenu.
Architecture ORB-SLAM3
----------------------
.. code-block:: text
┌─────────────────────────────────────────────────┐
│ ORB-SLAM3 │
│ │
│ Tracking Thread ──► Local Mapping Thread │
│ │ │ │
│ Feature ORB Map Points │
│ Matching KeyFrames │
│ │ │ │
│ Pose Estimation Loop Closing Thread │
│ (PnP + IMU) (DBoW2 + g2o) │
│ │ │
│ Atlas (Multi-Map) │
└─────────────────────────────────────────────────┘
Dépendances compilation
-----------------------
.. code-block:: bash
# Eigen3
sudo apt install libeigen3-dev
# OpenCV 4.x
sudo apt install libopencv-dev
# Pangolin (viewer 3D)
git clone https://github.com/stevenlovegrove/Pangolin
cd Pangolin && cmake -B build && cmake --build build
# g2o (inclus dans ORB-SLAM3)
# DBoW2 (inclus dans ORB-SLAM3)
# ORB-SLAM3
git clone https://github.com/UZ-SLAMLab/ORB_SLAM3
cd ORB_SLAM3 && chmod +x build.sh && ./build.sh
Paramètres SLAM — fichier YAML
--------------------------------
Voir ``config/orbslam3_stereo.yaml`` (à créer après calibration) :
.. code-block:: yaml
Camera.type: "KannalaBrandt8" # ou "Pinhole"
Camera.fx: 525.0
Camera.fy: 525.0
Camera.cx: 640.0
Camera.cy: 360.0
Stereo.b: 0.11 # baseline en mètres
Stereo.ThDepth: 35.0 # profondeur max (b * ThDepth pixels)
ORBextractor.nFeatures: 1000
ORBextractor.scaleFactor: 1.2
ORBextractor.nLevels: 8
Contraintes sous-marines
-------------------------
- **Texture** : eau lisse = peu de features. Pointer vers fond ou structure.
- **Absorption** : rouge absorbé > 3 m. Filtre passe-haut sur illumination.
- **Turbidité** : features instables. Réduire ``ThDepth``, augmenter ``nFeatures``.
- **Réfraction** : calibration en air ≠ en eau. Recalibrer si possible en eau.
Références
----------
:cite:`campos2021orbslam3`
:cite:`qin2019fusion`
:cite:`joshi2019survey`

59
docs/source/sources.bib Normal file
View File

@@ -0,0 +1,59 @@
% ORB-SLAM3 — Campos et al. 2021, IEEE Transactions on Robotics
@article{campos2021orbslam3,
author = {Campos, Carlos and Elvira, Richard and Gómez Rodríguez, Juan J.
and Montiel, José M. M. and Tardós, Juan D.},
title = {{ORB-SLAM3}: An Accurate Open-Source Library for Visual,
Visual-Inertial, and Multimap {SLAM}},
journal = {IEEE Transactions on Robotics},
volume = {37},
number = {6},
pages = {1874--1890},
year = {2021},
doi = {10.1109/TRO.2021.3075644},
}
% VINS-Fusion — Qin & Shen 2019
@article{qin2019fusion,
author = {Qin, Tong and Pan, Jie and Cao, Shaozu and Shen, Shaojie},
title = {A General Optimization-based Framework for Local Odometry
Estimation with Multiple Sensors},
journal = {arXiv preprint arXiv:1901.03638},
year = {2019},
url = {https://arxiv.org/abs/1901.03638},
}
% Calibration sous-marine — Ferrera et al. 2019
@inproceedings{ferrera2019underwater,
author = {Ferrera, Maxime and Moras, Julien and Trouvé-Peloux, Pauline},
title = {Real-Time Monocular Visual Odometry for Turbid and Dynamic
Underwater Environments},
booktitle = {Proceedings of the IEEE International Conference on Robotics
and Automation (ICRA)},
year = {2019},
pages = {9720--9726},
doi = {10.1109/ICRA.2019.8793818},
}
% Survey SLAM AUV — Joshi et al. 2019
@article{joshi2019survey,
author = {Joshi, Bharat and Rahman, Sharmin and Kalaitzakis, Michail
and Cain, Brennan and Johnson, James and Xanthidis, Marios
and Karapetyan, Nare and Hernandez, Aven and Henderson,
Thomas C. and Rekleitis, Ioannis},
title = {Experimental Comparison of Open Source Visual-Inertial-Based
State Estimation Algorithms in the Underwater Domain},
booktitle = {2019 IEEE/RSJ International Conference on Intelligent Robots
and Systems (IROS)},
year = {2019},
pages = {7227--7234},
doi = {10.1109/IROS40897.2019.8968049},
}
% OpenCV Learning — Bradski & Kaehler 2008
@book{bradski2008learning,
author = {Bradski, Gary and Kaehler, Adrian},
title = {Learning {OpenCV}: Computer Vision with the {OpenCV} Library},
publisher = {O'Reilly Media},
year = {2008},
isbn = {978-0596516130},
}

6
docs/source/sources.rst Normal file
View File

@@ -0,0 +1,6 @@
Bibliographie
=============
.. bibliography::
:all:
:style: unsrt

View File

@@ -0,0 +1,98 @@
Théorie — Baseline Stéréo
==========================
Modèle géométrique
------------------
Le système stéréo calibré suit le modèle trou d'aiguille rectifié.
Après rectification, les lignes épipolaires sont horizontales et
la disparité est uniquement sur l'axe X.
Relation profondeurdisparité
------------------------------
.. math::
Z = \frac{f \cdot B}{d}
Avec :
- :math:`Z` — profondeur en mètres
- :math:`f` — focale en **pixels** (après calibration)
- :math:`B` — baseline en **mètres**
- :math:`d` — disparité en **pixels**
Paramètres du système
---------------------
.. list-table::
:header-rows: 1
* - Paramètre
- Valeur
- Source
* - Focale estimée :math:`f`
- 525 px
- LifeCam HD-3000, résolution 1280×720
* - Baseline :math:`B`
- 0.11 m
- Support OpenSCAD, médiane 1012 cm
* - Disparité min :math:`d_{min}`
- 1 px
- Limite théorique
* - Disparité max :math:`d_{max}`
- 64 px
- StereoBM / SGBM config
Portée théorique
----------------
.. math::
Z_{max} = \frac{f \cdot B}{d_{min}} = \frac{525 \times 0.11}{1} = 57.75 \text{ m}
.. math::
Z_{min} = \frac{f \cdot B}{d_{max}} = \frac{525 \times 0.11}{64} \approx 0.9 \text{ m}
**Portée pratique sous-marin** : 0.5 m 5 m
La limite pratique est imposée par la **visibilité de l'eau** (turbidité,
diffusion), pas par la géométrie. En eau claire méditerranéenne,
portée max mesurée ≈ 8 m. En eau verte côtière : ≈ 23 m.
Pourquoi 1012 cm ?
--------------------
**Baseline trop courte** (< 5 cm) :
- Disparité trop faible → bruit dominant
- :math:`Z_{max}` réduit, peu de points 3D à grande distance
**Baseline trop longue** (> 20 cm) :
- Zone aveugle centrale grande (:math:`Z_{min}` augmente)
- Occultations importantes (objet vu par une seule caméra)
- Synchronisation temporelle plus critique
**Plage 1012 cm** :
- Compromise optimal pour portée 0.55 m
- Compatible avec gabarit BlueROV2 (largeur tube ~10 cm)
- Résolution en profondeur : :math:`\delta Z = Z^2 / (f \cdot B)` ≈ 4 cm à 2 m
Sensibilité à la calibration
-----------------------------
Une erreur de 1 mm sur la baseline :math:`B` induit une erreur
:math:`\delta Z / Z = \delta B / B \approx 0.9\%` sur toutes les profondeurs.
Conserver le support imprimé rigide et éviter le choc thermique
(dilatation différentielle PETG/aluminium).
Références
----------
:cite:`campos2021orbslam3` — ORB-SLAM3, précision stéréo-inertiel.
:cite:`ferrera2019underwater` — Calibration sous-marine, modèle réfraction.