From d36255cf62bcd7a85e3b942a6a4d51ffef1a9d31 Mon Sep 17 00:00:00 2001 From: Floppyrj45 Date: Sun, 19 Apr 2026 18:07:28 +0200 Subject: [PATCH] feat: Dockerfile BlueOS, deploy_pi.sh rsync, camera_mount.scad baseline 110mm Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 82 ++++++++++++++++++++++++++++++++++++++ config/.gitkeep | 0 hardware/camera_mount.scad | 74 ++++++++++++++++++++++++++++++++++ scripts/deploy_pi.sh | 73 +++++++++++++++++++++++++++++++++ 4 files changed, 229 insertions(+) create mode 100644 Dockerfile create mode 100644 config/.gitkeep create mode 100644 hardware/camera_mount.scad create mode 100644 scripts/deploy_pi.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dfca8f7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,82 @@ +# SLAM Stéréo BlueOS — Extension Docker +# Base: ROS2 Humble (Ubuntu 22.04) +# ORB-SLAM3 + Flask interface + +FROM ros:humble-ros-base AS base + +LABEL version="0.1.0" +LABEL description="SLAM Stéréo visuel pour AUV sous-marin — BlueOS Extension" +LABEL authors='[{"name": "Baptiste Moulin", "email": "claude@nowyouknow.fr"}]' +LABEL company='{"about": "AUV SLAM project", "name": "Baptiste Moulin", "email": "claude@nowyouknow.fr"}' +LABEL type="device-integration" +LABEL tags='["slam", "stereo", "vision", "auv", "underwater"]' +LABEL permissions='{"NetworkMode": "host", "Devices": ["/dev/video0", "/dev/video1"], "HostConfig": {"Privileged": false}}' + +ENV DEBIAN_FRONTEND=noninteractive +ENV ROS_DISTRO=humble + +# --- Dépendances système --- +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3-pip \ + python3-opencv \ + libopencv-dev \ + cmake \ + build-essential \ + git \ + wget \ + libssl-dev \ + libusb-1.0-0-dev \ + libeigen3-dev \ + libglew-dev \ + libpython3-dev \ + python3-numpy \ + python3-yaml \ + # Pangolin deps + libgl1-mesa-dev \ + libglu1-mesa-dev \ + freeglut3-dev \ + libwayland-dev \ + libxkbcommon-dev \ + wayland-protocols \ + && rm -rf /var/lib/apt/lists/* + +# --- Python dependencies --- +RUN pip3 install --no-cache-dir \ + flask>=3.0 \ + numpy>=1.24 \ + pyyaml>=6.0 \ + opencv-python-headless>=4.8 + +# --- Pangolin (viewer 3D ORB-SLAM3) --- +RUN git clone --depth 1 https://github.com/stevenlovegrove/Pangolin /opt/Pangolin && \ + cmake -S /opt/Pangolin -B /opt/Pangolin/build \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TOOLS=OFF \ + -DBUILD_EXAMPLES=OFF && \ + cmake --build /opt/Pangolin/build --parallel $(nproc) && \ + cmake --install /opt/Pangolin/build && \ + rm -rf /opt/Pangolin + +# --- ORB-SLAM3 dependencies (g2o, DBoW2 inclus dans ORB-SLAM3) --- +# Note: compilation complète ~15 min. Décommenter pour build final. +# RUN git clone --depth 1 https://github.com/UZ-SLAMLab/ORB_SLAM3 /opt/ORB_SLAM3 && \ +# cd /opt/ORB_SLAM3 && chmod +x build.sh && bash build.sh + +# --- Application SLAM --- +WORKDIR /app +COPY src/ ./src/ +COPY config/ ./config/ + +# Créer config/ si vide +RUN mkdir -p /app/config + +# --- Port Flask --- +EXPOSE 5000 + +# --- Healthcheck --- +HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:5000/ || exit 1 + +# --- Entrypoint --- +ENV PYTHONUNBUFFERED=1 +CMD ["python3", "src/interface/app.py"] diff --git a/config/.gitkeep b/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/hardware/camera_mount.scad b/hardware/camera_mount.scad new file mode 100644 index 0000000..6aadaa7 --- /dev/null +++ b/hardware/camera_mount.scad @@ -0,0 +1,74 @@ +// camera_mount.scad — Support stéréo pour 2x Microsoft LifeCam HD-3000 +// Baseline: 110 mm (médiane 10-12 cm optimal) +// Fixation: 4x M3 sur châssis AUV +// Matériau recommandé: PETG (résistance eau, impact) +// Auteur: Baptiste Moulin 2026 + +$fn = 60; + +// --- Paramètres principaux --- +BASELINE = 110; // mm entre axes optiques +CAM_W = 34; // largeur boîtier LifeCam (section base) +CAM_H = 34; // hauteur boîtier LifeCam +CAM_DEPTH = 10; // profondeur empreinte caméra dans le support +MOUNT_THICK = 6; // épaisseur plaque support +MOUNT_H = 50; // hauteur totale support +BOLT_D = 3.4; // diamètre trou M3 (passage libre) +BOLT_PITCH_X = 96; // entraxe vis de fixation AUV (X) +BOLT_PITCH_Y = 30; // entraxe vis de fixation AUV (Y) + +// --- Longueur totale de la plaque --- +PLATE_L = BASELINE + CAM_W + 10; + +module cam_cutout() { + // Empreinte caméra: rectangle + passage câble USB + cube([CAM_W, CAM_DEPTH, CAM_H], center=true); + // Slot câble USB (6x10 mm) en bas de l'empreinte + translate([0, 0, -CAM_H/2 + 5]) + cube([12, CAM_DEPTH + 2, 10], center=true); +} + +module bolt_holes_mount() { + // 4 trous M3 pour fixation sur châssis AUV + for (x = [-BOLT_PITCH_X/2, BOLT_PITCH_X/2]) + for (y = [-BOLT_PITCH_Y/2, BOLT_PITCH_Y/2]) + translate([x, y, 0]) + cylinder(d=BOLT_D, h=MOUNT_THICK + 2, center=true); +} + +module support() { + difference() { + // Corps principal + union() { + // Plaque horizontale + cube([PLATE_L, MOUNT_THICK, MOUNT_H], center=true); + // Renforts latéraux sur chaque caméra + for (side = [-1, 1]) + translate([side * BASELINE/2, MOUNT_THICK/2, 0]) + cube([CAM_W + 4, MOUNT_THICK * 2, MOUNT_H], center=true); + } + + // Empreinte caméra gauche + translate([-BASELINE/2, 0, 0]) + cam_cutout(); + + // Empreinte caméra droite + translate([BASELINE/2, 0, 0]) + cam_cutout(); + + // Trous de fixation AUV + bolt_holes_mount(); + + // Allègement central (triangle) + translate([0, 0, 0]) + cube([BASELINE - CAM_W - 8, MOUNT_THICK + 2, MOUNT_H - 16], center=true); + } +} + +// --- Rendu principal --- +support(); + +// --- Annotations (commentaires) --- +// Axes optiques à Z=0, Y=MOUNT_THICK+5 +// Baseline mesurée = BASELINE mm entre les 2 marques rouges +// Imprimer à 0.2 mm layer height, 40% infill gyroid, 3 périmètres diff --git a/scripts/deploy_pi.sh b/scripts/deploy_pi.sh new file mode 100644 index 0000000..c3a163d --- /dev/null +++ b/scripts/deploy_pi.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# Deploy SLAM stéréo sur Raspberry Pi via SSH/rsync +# Usage: bash deploy_pi.sh + +set -e + +# --- Variables --- +PI_USER="pi" +PI_PASS="raspberry" +PI_DEST="/home/pi/slam_stereo" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" + +# --- Argument --- +if [ -z "$1" ]; then + echo "[ERREUR] Usage: $0 " + echo "Exemple: $0 192.168.2.2" + exit 1 +fi +PI_HOST="$1" + +echo "[INFO] Déploiement vers $PI_USER@$PI_HOST:$PI_DEST" + +# --- Test connectivité --- +echo "[INFO] Test SSH..." +if ! sshpass -p "$PI_PASS" ssh -o StrictHostKeyChecking=no \ + -o ConnectTimeout=5 "$PI_USER@$PI_HOST" "echo 'SSH OK'" 2>/dev/null; then + echo "[ERREUR] Impossible de se connecter à $PI_HOST" + echo "[INFO] Vérifier: IP correcte, Pi allumé, sshpass installé" + exit 1 +fi + +# --- Créer dossiers sur Pi --- +echo "[INFO] Création des dossiers..." +sshpass -p "$PI_PASS" ssh -o StrictHostKeyChecking=no "$PI_USER@$PI_HOST" \ + "mkdir -p $PI_DEST/{src/calibration,src/slam,src/interface,config}" + +# --- Rsync src/ --- +echo "[INFO] Transfert src/..." +sshpass -p "$PI_PASS" rsync -avz --progress \ + -e "ssh -o StrictHostKeyChecking=no" \ + "$PROJECT_DIR/src/" \ + "$PI_USER@$PI_HOST:$PI_DEST/src/" + +# --- Rsync config/ --- +echo "[INFO] Transfert config/..." +sshpass -p "$PI_PASS" rsync -avz --progress \ + -e "ssh -o StrictHostKeyChecking=no" \ + "$PROJECT_DIR/config/" \ + "$PI_USER@$PI_HOST:$PI_DEST/config/" 2>/dev/null || echo "[WARN] config/ vide, skip" + +# --- Install dépendances Python --- +echo "[INFO] Installation dépendances Python..." +sshpass -p "$PI_PASS" ssh -o StrictHostKeyChecking=no "$PI_USER@$PI_HOST" bash << 'REMOTE' + set -e + pip3 install --upgrade pip --quiet + pip3 install opencv-python flask numpy pyyaml --quiet + echo "[OK] Dépendances installées" +REMOTE + +# --- Test Flask --- +echo "[INFO] Test Flask..." +sshpass -p "$PI_PASS" ssh -o StrictHostKeyChecking=no "$PI_USER@$PI_HOST" \ + "cd $PI_DEST && python3 -c 'import flask, cv2, numpy, yaml; print(\"[OK] Imports OK\")'" + +echo "" +echo "=== DEPLOY TERMINÉ ===" +echo "Interface web: http://$PI_HOST:5000" +echo "Démarrage manuel:" +echo " ssh $PI_USER@$PI_HOST" +echo " cd $PI_DEST && python3 src/interface/app.py" +echo "" +echo "Note BlueOS: utiliser aussi le Dockerfile pour extension native"