Software stack for a cownose-ray-inspired AUV with flexible pectoral fins and 6-DOF closed-loop navigation.
*T. Scudeletti, G. Bianchi et al., "From Fin Dynamics to Navigation Control: A Simplified Framework for Batoid-Inspired Underwater Locomotion", _ *
MAUI is a bio-inspired AUV that mimics the locomotion of a cownose ray, propelling itself through oscillating flexible silicone pectoral fins and steering with two caudal rudder fins. The key contribution of this project is a fully onboard, model-free 6-DOF closed-loop navigation system operating in open water without any external tracking — using only an IMU, a depth sensor, and GPS for resurfacing.
The control architecture is cascaded: a Madgwick-filter attitude estimator feeds a quaternion-based attitude regulator, which is wrapped by a depth PID and an outer GPS-assisted heading controller. All control logic runs in ROS 2 Jazzy inside a Docker container, making the software OS-independent and deployable identically on the robot (Raspberry Pi 5) and on a development machine.
Forward speed is not closed-loop controlled — it is set open-loop via the pectoral fin stroke amplitude A_m. The default value is configured in ros2_ws/src/maui_brain/cerebellum/config/BMF.yaml under start_wing. Increasing A_m raises thrust; decreasing it reduces speed.
The ROS 2 packages are organized under maui_brain, with each package taking inspiration from a functional region of the brain:
| Package | Brain Region | Role |
|---|---|---|
brain_stem |
Brain Stem | Low-level hardware drivers (IMU, pressure, PWM, GPS) |
cerebellum |
Cerebellum | Attitude and depth controllers |
frontal_lobe |
Frontal Lobe | High-level navigation and mission planning |
parietal_lobe |
Parietal Lobe | State estimation and sensor fusion |
temporal_lobe |
Temporal Lobe | Perception and camera processing |
occipital_lobe |
Occipital Lobe | Visual processing |
The top-level maui package holds the main launch files that orchestrate all subsystems. Hardware drivers for I²C sensors live as standalone packages (mpu9250, ms5837, gtu7_gps_comm, pwm_pca9685).
Maui/
├── docker/
│ ├── raspi_ros2/ # Docker setup for deployment on Raspberry Pi 5
│ └── maui_emulator/ # Docker setup for development on a personal computer
├── raspiOs_setup/
│ ├── maui_setup.sh # Raspberry Pi OS bootstrap script
│ └── raspi_api_interface/# Python HTTP servers that expose the Pi cameras to the container
├── ros2_ws/src/
│ ├── maui/ # Top-level package with main launch files
│ ├── maui_brain/ # Control logic packages (see table above)
│ ├── mpu9250/ # IMU driver
│ ├── ms5837/ # Pressure/depth sensor driver
│ ├── gtu7_gps_comm/ # GPS driver
│ └── pwm_pca9685/ # PWM controller driver
└── images/ # Diagrams and schematics
![]() Perspective view |
![]() Component layout |
- Raspberry Pi 5
- PCA9685 PWM controller
- MPU9250 9-axis IMU + magnetometer
- BlueRobotics MS5837-02BA depth/pressure sensor
- GTU7 GPS receiver
- 2× Raspberry Pi CAM 3 (CSI strip connector)
- 4× PowerHD 40 kg waterproof servos (pectoral fins)
- 2× servo-actuated caudal rudder fins
- DC-DC converter (2S LiPo → 5 V regulated)
The Raspberry Pi cameras connect via CSI strip connectors and are not directly accessible from inside the Docker container. A Flask-based HTTP server (raspiOs_setup/raspi_api_interface/fast_cameras_server.py) runs on the host OS and exposes both cameras simultaneously over a local HTTP endpoint that the container consumes.
- Docker with the Compose plugin
- Git
Two setup scripts are provided in raspiOs_setup/:
| Script | Purpose |
|---|---|
maui_setup.sh |
Step-by-step reference — run commands individually, useful for understanding each step or troubleshooting |
maui_auto_setup.sh |
Fully automated — runs end-to-end on a fresh Raspberry Pi OS (Bookworm) install without any interactive prompts |
Automated setup (recommended for a fresh Pi):
bash raspiOs_setup/maui_auto_setup.shThe script handles: system update, I2C/UART activation, SSH, Docker install, gpsd configuration, camera bridge dependencies, repo clone, Docker image build, and systemd autostart for the camera bridge. The container itself restarts automatically on boot via Docker's restart: unless-stopped policy.
What runs at boot (after setup + reboot):
- Docker daemon starts automatically (systemd service installed with Docker)
- Camera bridge starts automatically (
maui-camera.service) — exposes CSI cameras over HTTP - MAUI container restarts automatically (Docker restart policy) — builds the workspace and launches
circle_path.launch.py
Attaching to the running container:
docker exec -it maui_jazzy bashChanging the default launch file or understanding all available missions and tests:
→ See ros2_ws/src/maui/README.md
Detailed instructions: docker/maui_emulator/ (README coming soon)
# 1. Set the path to your local ros2_ws in docker/maui_emulator/.env
# PROJECT_DIRECTORY=/path/to/your/ros2_ws
# 2. Build and start the container
cd docker/maui_emulator
docker compose up -d
# 3. Attach and work
docker exec -it maui_jazzy bashAn X server (e.g., VcXsrv on Windows, XQuartz on macOS) is required for GUI tools such as RViz, for Foxglove the bridge should work without.
Setup the raspberry pi on the same Wi-Fi network as your development machine. The robot will acquire an IP address via DHCP. You can find the IP address by checking your router's connected devices or using a network scanning tool (e.g., nmap).
See LICENSE.

.png)



