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:
20
docs/Makefile
Normal file
20
docs/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
SOURCEDIR = source
|
||||
BUILDDIR = build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
35
docs/make.bat
Normal file
35
docs/make.bat
Normal file
@@ -0,0 +1,35 @@
|
||||
@ECHO OFF
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
REM Command file for Sphinx documentation
|
||||
|
||||
if "%SPHINXBUILD%" == "" (
|
||||
set SPHINXBUILD=sphinx-build
|
||||
)
|
||||
set SOURCEDIR=source
|
||||
set BUILDDIR=build
|
||||
|
||||
%SPHINXBUILD% >NUL 2>NUL
|
||||
if errorlevel 9009 (
|
||||
echo.
|
||||
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
|
||||
echo.installed, then set the SPHINXBUILD environment variable to point
|
||||
echo.to the full path of the 'sphinx-build' executable. Alternatively you
|
||||
echo.may add the Sphinx directory to PATH.
|
||||
echo.
|
||||
echo.If you don't have Sphinx installed, grab it from
|
||||
echo.https://www.sphinx-doc.org/
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
if "%1" == "" goto help
|
||||
|
||||
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
goto end
|
||||
|
||||
:help
|
||||
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
|
||||
|
||||
:end
|
||||
popd
|
||||
106
docs/source/blueos.rst
Normal file
106
docs/source/blueos.rst
Normal 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
101
docs/source/calibration.rst
Normal 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.3–1.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
38
docs/source/conf.py
Normal 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']
|
||||
98
docs/source/deployment.rst
Normal file
98
docs/source/deployment.rst
Normal 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
74
docs/source/hardware.rst
Normal 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 (0–300 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 10–12 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
24
docs/source/index.rst
Normal 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`
|
||||
68
docs/source/navigator_imu.rst
Normal file
68
docs/source/navigator_imu.rst
Normal 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
|
||||
- 100–400 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
134
docs/source/slam_stack.rst
Normal 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
59
docs/source/sources.bib
Normal 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
6
docs/source/sources.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Bibliographie
|
||||
=============
|
||||
|
||||
.. bibliography::
|
||||
:all:
|
||||
:style: unsrt
|
||||
98
docs/source/theory_baseline.rst
Normal file
98
docs/source/theory_baseline.rst
Normal 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 profondeur–disparité
|
||||
------------------------------
|
||||
|
||||
.. 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 10–12 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 : ≈ 2–3 m.
|
||||
|
||||
Pourquoi 10–12 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 10–12 cm** :
|
||||
|
||||
- Compromise optimal pour portée 0.5–5 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.
|
||||
Reference in New Issue
Block a user