An autonomous sailboat system based on Dragonforce 65 hull, running on Orange Pi Zero 2W with ROS2. The system includes comprehensive sensor integration, autonomous navigation, and safety monitoring.
argo.freecad.3d.webm
- Mar 2026: Version 4 of argo PCB with bug fixes, wind sensor on separate I2C bus, and new buzzer. Version 3 of the wind sensor PCB with RGBW LED controller. See Argo2: Robot Sailboat slides presented online at Embodied Intelligence Conference 20 March 2026.
- Feb 2026: Updated wind sensor design PCB and housing complete. 3D parts for wind sensor I2C cable and mast step up completed and printed.
- Jan 2026: Argo main PCB version 3 completed and seems fully functional with no surgery needed.
- Aug-Dec 2025: Intense development of new Argo PCB and ROS2 software framework. System services developed (see
power_control/argo_power_control.pyandlaunch/argo_lifecycle_manager.py) along with robust lifecycle management and battery/power control. - Oct-Nov 2025: Developed first version of Argo simulator.
- See simulator/sailboat-playground/README.md for usage and architecture.
- Additional docs: Simulation Guide, Debug Simulation Guide
Pick Argo (boat) or Host (PC) below. ROS 2 must match your Ubuntu LTS: 22.04 (Jammy) → Humble; 24.04 (Noble) → Jazzy. Use the official ROS 2 Ubuntu (deb) install page that corresponds to your ROS release.
On the robot, the stack targets Ubuntu 22.04–based Armbian and ROS 2 Humble. Bring up I²C/UART/PWM overlays, the radio/servo kernel module, Python dependencies, systemd services, and power control as described in the launch tree.
cd ~/argo # or your clone path
sudo apt update && sudo apt upgrade -y
# Install ROS 2 Humble (.deb), then in each shell you use for builds:
# source /opt/ros/humble/setup.bash
make install-all # Python deps + optional hardware (see Makefile / messages)
make install-argo-cli
source ~/.bashrc
make -C launch install # install systemd units; enable per docs1. Flash Orange Pi OS using Orange Pi Imager or equivalent.
2. Initial system setup
sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip python3-dev build-essential
sudo apt install i2c-tools device-tree-compiler git
sudo apt install ros-humble-desktop3. Clone repository
cd /home/orangepi
git clone https://github.com/SensorsINI/argo.git
cd argo4. Python and ROS helpers
make install-python-deps # requirements.txt on the boat
# If needed:
sudo apt install python3-rclpy python3-std-msgs python3-geometry-msgs5. Hardware configuration
Edit /boot/orangepiEnv.txt and add overlays:
overlays=pi-i2c0 disable-uart0 ph-uart5 pi-pwm2 pi-pwm4
user_overlays=argo_radio_servo_overlay
Build and load the PWM capture module:
cd ~/argo/nodes/pwm_capture_module
make all
sudo modprobe argo_radio_servo_module # or rebootAdd your user to hardware groups:
sudo usermod -a -G i2c,dialout $USER
# log out and back in6. Verify
sudo i2cdetect -y 0
lsmod | grep argo
ls -la /sys/kernel/argo_radio_servo/
sudo cat /dev/ttyS57. CLI and services
make install-argo-cli && source ~/.bashrc
make -C launch install
sudo systemctl daemon-reload
sudo systemctl enable argo_launch.serviceUse this on a laptop or workstation for local simulation (asim), Foxglove Studio (same Wi‑Fi, VPN, or SSH tunnel), log playback, and shore-side scripts. The boat still runs ROS 2 on the Orange Pi; your host subscribes/records like any ROS 2 client. LoRa is a boat link—the monitoring machine uses normal network ROS 2 or recorded bags unless you run a separate LoRa gateway stack.
Prerequisites: Ubuntu 22.04 or 24.04 (see mapping to Humble/Jazzy above), git, make, sudo, and network access for apt.
One-shot bootstrap (Ubuntu 22.04 or 24.04):
cd /path/to/argo
make host-setup
source ~/.bashrc # reload Argo dotfiles in this terminal (or open a new tab)
# Dotfiles auto-source the first ROS found under /opt/ros (jazzy, iron, humble, rolling) when ROS_DISTRO is unset.
source .venv/bin/activate # optional; pip tooling (argcomplete, pyglet, …)
asimIf a command in this terminal cannot find rclpy or ros2 right after host-setup, the ROS underlay is not loaded yet: run source ~/.bashrc (as above), or explicitly source /opt/ros/humble/setup.bash / source /opt/ros/jazzy/setup.bash matching your install.
make host-setup refuses to run on Orange Pi (use make install-all on the boat). It:
- Adds
/etc/apt/sources.list.d/ros2-latest.listonly if no file already references packages.ros.org/ros2/ubuntu (avoids a secondSigned-Byif you installed ROS 2 from the official doc first) - Installs
ros-<distro>-ros-basewhen/opt/ros/<distro>is absent (Jammy →humble, Noble →jazzy, or override withROS_DISTRO=) - Runs
make install-deps(singleapt-get update, then Argo’s ROS .deb set, Foxglove bridge, MCAP storage) - Runs
make setup-venv(creates.venvwith uv if available, otherwisepython3 -m venv, and installsrequirements-host.txt) thenmake install-python-deps(same host requirements file again into.venv—idempotent on a PC) - Runs
make install-argo-cliandmake submodule-init(install-argo-cliappendssource <repo>/dotfiles/bashrcto~/.bashrc; that file auto-sources/opt/ros/<distro>/setup.bashwhenROS_DISTROis not already set)
Tab completion (optional): Global argcomplete is not installed automatically on every shell (keeps login fast). After host-setup, run once: activate-global-python-argcomplete3 --user or activate-global-python-argcomplete --user, or see dotfiles/README.md — Tab Completion Setup.
Force a distro explicitly, e.g. on non-LTS or mixed images:
make host-setup ROS_DISTRO=jazzyIf apt-get update reports conflicting Signed-By for packages.ros.org/ros2/ubuntu, you have two ROS 2 source files—keep one. For example, if you already used the official installer, remove Argo’s duplicate and refresh: sudo rm -f /etc/apt/sources.list.d/ros2-latest.list && sudo apt-get update.
install-ros2-apt-repo checks for an existing ROS 2 source with sudo grep because some sources.list.d entries are root-only; without that, Make could miss your working repo and add a second file.
Foxglove: with ROS sourced on the machine that runs the bridge, start ros2 run foxglove_bridge foxglove_bridge and connect from Foxglove Studio to ws://<that-host-ip>:8765.
make host-setup— host-only full bootstrap (see above)make install-deps— ROS packages for the currentROS_DISTRO(Foxglove, MCAP, …)make install-python-deps— robot usesrequirements.txt; host usesrequirements-host.txt(prefers.venvif present)make install-hardware— PWM module (boat)make install-all— boat-oriented dependency + hardware pathmake -C launch …— lifecycle systemd helpers
After make install-argo-cli, common aliases include al / aq / ars (services), as / asq (status), asim (local sim), ar / ac (recording), alog, ah. Run make help and see dotfiles/.
The Argo system consists of multiple ROS2 nodes that work together to provide autonomous sailing capabilities:
- Sensor Nodes: GPS (u-blox NEO-M9N), IMU (Adafruit BNO085), Wind sensors (3x Sensirion SDP3x), Battery/Water monitoring
- Control Interface: PWM capture for radio control and servo output
- Autonomous Control: Navigation and sail trimming algorithms
- Safety Systems: Manual override, battery monitoring, water intrusion detection
See the Argo autonomous sailboat in action at the 2024 CCNW (before current waterproofing and PCB developements): Argo Sailboat Demo
The main PCB design for Argo is available in the pcb/ folder. The latest board version is rev4, which contains the current sailboat control and sensor interface design.
- Orange Pi Zero 2W (Allwinner H618 SoC)
- GPS: u-blox NEO-M9N via UART5 (/dev/ttyS5)
- IMU: Adafruit BNO085 9-DOF Orientation IMU via I2C0 (0x4a)
- Wind Sensor: 3x Sensirion SDP3x differential pressure sensors via I2C0 (0x21, 0x22, 0x23). This PCB includes an RGBW LED and its I2C controller PCA9632 at individual address 0x62 (0x70 is LED All Call).
- Design files: See
pcb/WindSensor/WindSensor-rev1/directory for full hardware schematics, layout, and BOM.
- Design files: See
- ADC: MAX11612 for battery/water sensing via I2C0 (0x34)
- Environment: SHT45 temperature/humidity via I2C0 (0x44)
- PWM I/O: Custom kernel module for radio control and servo interfaces with high impedance safety mode
- LORA: Long range radio based on RA-01 radio module from ai-thinker.com using SX1276 LORA chip
The Argo system is designed to handle frequent SBC hardware replacements (due to damage) while maintaining network identity. The WiFi MAC address is frozen to a consistent value (c8:26:e2:6c:58:ba) stored in network/ARGO_MAC_ID.txt and committed to git. This ensures:
- Network Stability: Same MAC address across hardware changes maintains network access (uzh-iot, ZeroTier, tobi-wlan)
- SD Card Portability: Same SD card works seamlessly with different SBC hardware
- Automatic Configuration: Run
make freeze-mac-addressafter hardware replacement to restore network identity
See Network Improvements Documentation for details.
The Argo system uses a shared control circuit design that allows both radio control and autonomous software control of servos through a fail-safe high impedance switching mechanism:
-
Sail Winch Servo: Joysway #880545
- Type: Standard sail winch servo with high-precision plastic gears
- Operating voltage: 4.8V to 6.0V
- PWM frequency: 1520μs/50Hz
- Input impedance: 12kΩ (measured)
- Circuit resistor: 3.3kΩ (optimized for proper signal level)
-
Rudder Servo: Joysway #881504
- Type: Digital metal gear servo
- Operating voltage: 4.8V to 6.0V
- PWM frequency: 1520μs/330Hz
- Input impedance: 400kΩ (measured)
- Circuit resistor: 10kΩ (standard value works well)
The hardware implements a fail-safe shared control circuit where:
- High Impedance Safety Mode: When PWM outputs are disabled (high impedance), radio control signals pass through resistors directly to servo inputs
- Software Control Mode: When PWM outputs are enabled, software generates servo control signals
- Voltage Divider Considerations: Resistor values are optimized based on servo input impedance:
- Sail servo: 3.3V × (12kΩ / (3.3kΩ + 12kΩ)) = 2.6V (adequate signal level)
- Rudder servo: 3.3V × (400kΩ / (10kΩ + 400kΩ)) = 3.2V (excellent signal level)
- PI11 (Pin 7): Radio Rudder Input - GPIO input with interrupt capability
- PI13 (Pin 26): Radio Sail Input - GPIO input with interrupt capability
- PI12 (Pin 33): Servo Rudder Output - PWM2 channel, high impedance when disabled
- PI14 (Pin 16): Servo Sail Output - PWM4 channel, high impedance when disabled
This design ensures radio control always works when software is not running, providing maximum safety for autonomous sailboat operation.
flowchart TB
subgraph OUTPUTS[Output Nodes]
RSR[rudder_sail_radio primary actuation output]
LORA[lora long range communications]
end
CTRL[controller primary decision and control logic]
subgraph SAFETY[Critical Safety Services]
BW[battery_water critical]
LA[launch critical]
end
subgraph SENSORS[Sensor Input Layer]
GPS[gps]
IMU[imu BNO085]
ANEM[anem]
end
VR[Visualization and Recording]
GPS --> CTRL
IMU --> CTRL
ANEM --> CTRL
CTRL --> RSR
BW --> LA
LA --> CTRL
CTRL --> VR
CTRL -.-> LORA
The Argo system follows a modular ROS2 architecture with clear separation of concerns:
Directory Structure:
nodes/- Individual ROS2 nodes (Python-based sensor interfaces)launch/- Lifecycle management, systemd services, and launch configurationspower_control/- Power management system (separate ROS2 package)foxglove/- Visualization layouts for Foxglove Studiosimulator/- Sailboat simulation submodule (sailboat-playground)
- Systemd Services Architecture - Service dependencies, boot sequence, and troubleshooting
- Network Improvements - WiFi reconnection, MAC address cloning, and NetworkManager configuration
- ZeroTier VPN Setup - ZeroTier VPN configuration, SSH access, and network management
- Power Control System - Power button, LED control, and graceful shutdown
- Systemd Integration - Launch system and lifecycle management
- Shutdown Fixes - Shutdown procedure fixes and improvements
- LED Status Guide - LED status display and hatch cover indicators
- Simulation System Overview - Sailboat simulation framework
- Simulation Documentation - Simulation setup and usage
- Debug Simulation - Debugging simulation issues
- I2C Configuration - I2C bus setup and troubleshooting
- LoRa (onboard ↔ shore) - SX1276 / Waveshare hardware, link parameters, packet header
- IMU BNO085 - C++ driver, Python bridge, calibration,
argo_bno085service - Thermal monitoring (SBC) - Orange Pi GPU/CPU/DDR temperature logging (
argo_thermal_monitor) - Watchdog Configuration - Watchdog setup for Orange Pi Zero 2W
- CPU Frequency Tuning - CPU governor configuration
- Battery & Power Monitoring - Battery monitoring system
- Battery Panel Setup - Battery panel configuration
- SD Card Backup - SD card backup procedures
- DVFS Userspace Access - Dynamic voltage and frequency scaling
- Foxglove Visualization - Real-time visualization setup
- Foxglove Debugging - Debugging Foxglove issues
- Foxglove Joystick Setup - Joystick control configuration
- 3D Visualization - 3D visualization configuration
- Visualization Marker Persistence - Marker persistence in visualization
- Adding Sailing Maps - Map integration guide
- Maps Documentation - Sailing area maps
- Remote Desktop VNC - VNC remote desktop setup
- Web Dashboard - Mobile-friendly web interface
- CLI Completion - Command-line completion setup
- Completion Quickstart - Quick start guide for CLI completion
- MOTD Customization - Message of the day customization
- ROS2 Nodes - Node documentation and configuration
- Scripts - Utility scripts documentation
- Dotfiles Setup - CLI aliases and shell configuration
- Persistent Logging - Logging configuration
Argo includes comprehensive simulation support for development and testing:
Local Simulation:
- Runs simulator directly on Orange Pi
- Uses sailboat-playground or mock simulator
- Excludes conflicting hardware nodes (GPS, IMU, anemometer, radio control)
- Perfect for algorithm development and testing
Remote Simulation:
- Offloads CPU-intensive simulation to remote machine
- SSH tunnel for ROS2 communication
- Centralized configuration management
- Ideal for resource-constrained environments
Quick Start:
# Local simulation
python3 launch/argo_lifecycle_manager.py simulate_local
# Remote simulation (requires setup)
python3 launch/argo_lifecycle_manager.py simulate_remote
# Or use helper scripts (equivalent flow):
./scripts/remote_simulator_tunnel.sh &
python3 scripts/remote_simulator_launch.py &
./scripts/launch_simulator_remote.shCentral control hub for the entire Argo system:
argo_lifecycle_manager.py- Core lifecycle management with intelligent monitoringargo_*.sh- Shell scripts for start/stop/restart/status operationsargo-launch.service- Systemd service configurationargo_gui.py- GTK-based status monitoring GUIargo_storage_monitor.py- Storage space monitoring and notificationsMakefile- Service installation and management automation
Hardware interface and control nodes:
- Sensor Nodes:
gps.py,imu.py,anem.py,argo_battery_water.py,temp_monitor.py - Control Nodes:
rudder_sail_radio.py,controller.py,record.py pwm_capture_module/- Custom kernel module for radio control and servo interfaces- Configuration files:
argo.yaml, calibration data, and support utilities
Standalone ROS2 package for power button and LED control:
argo_power_control.py- Main power control node with GPIO management- Hardware Functions: Power button monitoring, LED patterns (heartbeat/SOS), graceful shutdown
- ROS2 Services: LED control, system health monitoring
Makefile- Independent installation and service management
Custom PCB development for production-ready integration:
argo-v9-stable/- Current stable PCB design (KiCad project files)datasheets/- Component specifications and reference materialsorange-pi/- Orange Pi Zero 2W integration documentation and pin definitions- Bill of Materials: Component sourcing and assembly documentation
Foxglove Studio integration for live system monitoring:
argo_ros2.json- Pre-configured dashboard layout for Argo sailboatcustom-argo-panel/- TypeScript custom panel for specialized boat visualizationsetup_foxglove.sh- Automated Foxglove Bridge configuration and startup
Optional system-level monitoring services for debugging and development:
Makefile- Installation and management of system monitoring servicesservices/- Systemd service files for system monitoringscripts/- Monitoring scripts for boot history, memory, processes, etc.- Not installed by default - Use
make install-system-monitoringto install
Core ROS2 Nodes:
gps.py- GPS receiver interface (UART5, u-blox NEO-M9N)bno085.py- 9-DOF Orientation IMU with sensor fusion (I2C, Adafruit BNO085)anem.py- Wind sensor array (3x SDP3x pressure sensors)argo_battery_water.py- Power monitoring and safety systemsrudder_sail_radio.py- Radio control input and servo output interfacecontroller.py- Autonomous navigation and sail control algorithmsrecord.py- Data recording management (ROS2 bag files)temp_monitor.py- System temperature monitoringargo_unified_simulator_bridge.py- Unified simulator bridge for local and remote simulation
The Argo system uses a sophisticated lifecycle management approach centered around argo_lifecycle_manager.py:
Key Features:
- Real-time Monitoring: Active process detection during startup stabilization (not static sleeps)
- Failure Detection: Immediate FATAL error detection and reporting from systemd journal
- Auto-restart: Configurable restart policies with exponential backoff
- Graceful Shutdown: Proper cleanup and process termination
- Status Reporting: Comprehensive system health monitoring
Lifecycle Management Modes:
python3 launch/argo_lifecycle_manager.py run # Launch all nodes
python3 launch/argo_lifecycle_manager.py stop # Graceful shutdown
python3 launch/argo_lifecycle_manager.py restart # Restart all nodes
python3 launch/argo_lifecycle_manager.py status # Show system status
python3 launch/argo_lifecycle_manager.py monitor # Continuous monitoring
python3 launch/argo_lifecycle_manager.py simulate_local # Local simulation mode
python3 launch/argo_lifecycle_manager.py simulate_remote # Remote simulation modeCritical Node Management:
- Critical Nodes:
rudder_sail_radio.py,controller.py(essential for boat operation) - Success Criteria: All critical nodes + minimum 3 total nodes running
- Failure Handling: Intelligent restart with failure analysis and error reporting
Startup Monitoring Pattern:
- Launch Phase - Start all node processes
- Detection Phase - Wait for nodes to register (30s timeout)
- Stabilization Phase - Active monitoring for failures (15s with 1s intervals)
- Validation Phase - Final status check and success determination
Systemd Integration:
- Service:
argo-launch.serviceruns lifecycle manager in continuous mode - Dependencies: Waits for network and hardware module initialization
- Restart Policy: Automatic restart on failure with 5-second delay
- Environment: ROS2 Humble sourcing and logging configuration
cd ~/argo
source /opt/ros/humble/setup.bash
python3 launch/argo_lifecycle_manager.py run# Test individual sensors with debug output
python3 nodes/gps.py --debug
python3 nodes/bno085.py bridge # IMU bridge mode
python3 nodes/bno085.py status # Check IMU health
python3 nodes/anem.py --debug
python3 nodes/argo_battery_water.py --debug
python3 nodes/rudder_sail_radio.py
python3 nodes/controller.py# Monitor ROS2 topics
ros2 topic list
ros2 topic echo /battery_voltage
ros2 topic echo /anem_speed_angle_temp
ros2 topic echo /rudder_sail_radiogps.py: GPS interface via UART5, publishes/gps_databno085.py: Adafruit BNO085 IMU with sensor fusion, publishes/compass,/pose,/accel,/gyro,/imu_healthanem.py: Wind speed/direction from 3 pressure sensors, publishes/anem_speed_angle_tempargo_battery_water.py: Power and safety monitoring, publishes battery/water alertsrudder_sail_radio.py: Radio control interface and servo outputcontroller.py: Autonomous navigation controllerargo_unified_simulator_bridge.py: Unified simulator bridge for local and remote simulationlora.py: Long range radio node for LORA module
argo.yaml: Main control parameters (mode, gains, etc.)argo.env: ROS2 environment variables for systemd servicesRTIMULib.ini: IMU calibration and sensor fusion settings
- High Impedance Safety Mode: Servo outputs default to high impedance (PWM disabled), allowing radio control to pass through directly to servos via resistor network
- Manual Override: Human can take control via radio at any time, with immediate priority over autonomous control
- Shared Control Circuit: Fail-safe design where radio control always works when software is not running
- Battery Monitoring: Automatic low battery alerts (7.2V threshold)
- Water Intrusion Detection: Immediate alerts on water sensor activation
- Sensor Fault Detection: Automatic reconnection and error handling
- Timeout Protection: Safe defaults if communication is lost
To plot recorded bag file data, see argo-plots-2025.py (or argo-plots-2023.py).
- I2C Permission Errors: Ensure user is in
i2cgroup - UART Permission Errors: Ensure user is in
dialoutgroup - PWM Module Not Loading: Check device tree overlay installation
- Sensor Not Found: Verify I2C connections and addresses
- GPS No Data: Check UART5 overlay and baud rate settings
- Servo Low Signal Levels: Check servo input impedance and adjust resistor values accordingly:
- High-power servos (e.g., winch servos) may have low input impedance (12kΩ) requiring smaller resistors (3.3kΩ)
- Standard digital servos typically have high input impedance (400kΩ) working well with 10kΩ resistors
# Check system health
ah # show aliases
adevcheck # check for argo devices present and communicating
alog # follow argo logs - see help options
sudo i2cdetect -y 0 # check i2c bus
ros2 topic list
ros2 node list # check nodes
systemctl status argo-launch.serviceExciting developments are underway for 2025:
- Custom PCB Design: A dedicated PCB is being designed to integrate all sensors and control systems into a single, robust board
- Enhanced Seaworthiness: Significant improvements to waterproofing, structural integrity, and marine-grade components for extended autonomous operation
- Production Readiness: Moving from prototype to production-ready autonomous sailboat system
For detailed technical documentation, see the Google Doc README
BSD License - See package.xml for details
