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.
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
- 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)
- 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 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.
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
- Simulation System Overview
- Power Control System
- Foxglove Visualization
- Development Workflow
- Systemd Integration
- Simulation Documentation
- ROS2 Conversion Summary
- Threading Architecture
- CPU Frequency Tuning
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
# Download Orange Pi OS from official website
# Use Orange Pi Imager or similar tool to flash the OS# Boot the system and connect via SSH
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install essential packages
sudo apt install python3-pip python3-dev build-essential
sudo apt install i2c-tools device-tree-compiler git
sudo apt install ros-humble-desktop # ROS2 Humblecd /home/orangepi
git clone https://github.com/SensorsINI/argo.git
cd argo# Install Python runtime dependencies
make install-python-deps # installs from requirements.txt
# Install ROS2 dependencies (if not already installed)
sudo apt install python3-rclpy python3-std-msgs python3-geometry-msgsEdit /boot/orangepiEnv.txt:
sudo nano /boot/orangepiEnv.txtAdd these overlays:
overlays=pi-i2c0 disable-uart0 ph-uart5 pi-pwm2 pi-pwm4
user_overlays=argo_radio_servo_overlay
cd ~/argo/nodes/pwm_capture_module
make all
# Reboot or load the module manually after install
sudo modprobe argo_radio_servo_module# Add user to required groups
sudo usermod -a -G i2c,dialout $USER
# Logout and login again for group changes to take effect# Check I2C devices (should show: 21 22 23 34 44 4a)
sudo i2cdetect -y 0
# Check PWM kernel module
lsmod | grep argo
ls -la /sys/kernel/argo_radio_servo/
# Check UART GPS (should show NMEA data)
sudo cat /dev/ttyS5# Install Argo CLI (shell aliases and functions)
make install-argo-cli
# Activate CLI in current terminal
source ~/.bashrc
# Install and configure system services (optional)
make -C launch install
sudo systemctl daemon-reload
sudo systemctl enable argo-launch.serviceThe repository includes a comprehensive Makefile system for easy management:
Top-level Makefile targets:
make install-deps- Install ROS2 dependencies (foxglove-bridge)make install-python-deps- Install Python runtime dependenciesmake install-hardware- Install PWM capture modulemake install-all- Complete hardware and dependency setupmake install-argo-cli- Install shell aliases and functionsmake -C launch start- Start Argo system with monitoringmake -C launch stop- Stop Argo systemmake -C power_control install- Install power control system
Shell aliases (available after make install-argo-cli):
al- Launch Argo service with monitoringaq- Quit/stop Argo servicears- Restart Argo serviceas- Show Status Shows a comprehensive status of the Argo system, including:- Service status (
argo_launch_standard.service,argo_power_control.service, etc.) - Running ROS2 nodes and their health
- System diagnostics (CPU, memory, temperature, battery)
al: Start theargo_launch_standard.serviceaq: Stop theargo_launch_standard.servicears: Restart theargo_launch_standard.service
Tails the logs for all major Argo services with color-coding.
Starts the Argo system in local simulation mode using ros2 launch.
ar- Start data recording (via ROS2 service)ac- Stop data recording (via ROS2 service)am- Monitor mode for lifecycle managementag- Launch Argo GUIargo_status- Detailed system status checkargo_help- Show detailed help information
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
