Difference between revisions of "Autopilot"

From 'Engineers of Innovation Wiki'
Jump to navigation Jump to search
 
(17 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Platform ==
== Platform ==
Ease of development dictated the choice to run the control loop on existing hard- and software. which was chosen to be Ardupilot running on a Beaglebone blue.  
Ease of development dictated the choice to run the control loop on existing hard- and software, which was chosen to be Ardupilot running on a [https://docs.cubepilot.org/user-guides/autopilot/the-cube-module-overview orange cube].
[[File:Ardupilot.jpg|thumb|Ardupilot PCB with the orange cube mounted.]]
To make use for our application a PCB has been designed to integrate into the hydrofoil design.


== Setup ==
To connect to the ardupilot on the cube for tweaking settings and tuning control loops, [https://ardupilot.org/planner/docs/mission-planner-overview.html Mission Planner] is used. The control logic itself runs as a Lua script on the cube (see [[#Lua control script|Lua control script]]). The following sections describe the tweaked settings and the on-board script.


for the beagle bone setup follow [https://ardupilot.org/copter/docs/common-beagle-bone-blue.html this] tutorial. The version used in this tutorial is old. Make sure to use version 4.3.1 using the command bellow.  
== Hardware ==
The cube is a plug-and-play unit and therefore does not need setup changes in the underlying ardupilot software. Only necessary settings should be tweaked.


Apart from the settings, tuning needs to be done in Mission Planner; this can only be done with the solar boat in the water and therefore no values are known for now.


<code>sudo wget -O /usr/bin/ardupilot/arduplane https://firmware.ardupilot.org/Plane/stable-4.3.1/blue/arduplane</code>
The ardupilot PCB supports three servo motors, two front and one back motor. It has two isolated power supplies for the servo motors. Support for CAN and the cube is powered by the 24V input from the CAN connection.


== Relevant links for setting up Ardupilot ==
It has its own GPS antenna and four UART serial ports, where Serial1 is used for the MAVLINK connection to Mission Planner running on a laptop. The two ultrasonic height sensors connect over the '''CAN bus''' (through an RS485-to-CAN interface PCB), not the cube's UART ports; the Lua control script reads them to keep the boat at its target ride height so it can 'surf' over waves.
 
For steering on foils an extra MCU is added onto the board, namely the ATSAMD20E18A. This MCU receives the steering position from the rudder and forwards it (it is intended to be put on the CAN bus for the control system to use).
 
== Height Sensors ==
Currently testing ultrasonic height sensors, the RS485 version of the DYP-A02YY4W-V2.0, with a CAN-interface PCB in between that places the readings on the CAN bus.
 
Each sensor broadcasts a 3-byte frame at 8&nbsp;Hz: byte 0 is a status enum (0x02 = Operational, anything else = no valid reading), bytes 1–2 are the measured height in millimetres (uint16, little-endian). The front-left sensor uses CAN ID 0x011 and the front-right 0x012 (see [[#CAN Bus Format|CAN Bus Format]]).
 
The sensors are mounted as far forward and outboard as possible to stay clear of the bow wake (CAD: 3.8&nbsp;m forward, 0.23&nbsp;m left/right, 0.175&nbsp;m above the IMU). The trade-off is that their reading changes strongly with roll; the Lua script presents each sensor to ArduPilot as a downward scripting rangefinder (so ArduPilot median-filters and logs them) and applies a roll/pitch + lever-arm correction before using the values for control (see [[#Lua control script|Lua control script]]).
 
== Lua control script ==
The foil control logic runs as a Lua script on the cube (in the project git). It is a '''cascade''' that leans on ArduPilot's tested C++ attitude loop rather than re-implementing control in Lua:
 
* '''Inner loop — ArduPlane FBWA (mode 5):''' stabilises pitch and roll attitude from the IMU and drives the three foils as control surfaces. The two front foils are configured as elevons and the rear foil as an elevator output.
* '''Outer loop — the Lua script:''' reads the two CAN height sensors, computes a roll/pitch + lever-arm-corrected ride height, and turns the height error into a gentle pitch-target bias on the pitch input channel while holding roll level. Vertical-velocity damping uses the EKF's IMU-fused velocity estimate.
 
The rear foil is driven over CAN: the script reads ArduPilot's elevator output and sends it as a servo command (ID 0x010).
 
'''No RC transmitter''' is fitted — throttle and rudder are handled separately. Attitude targets are supplied via RC channel overrides from the script, refreshed every loop. A hardware '''enable pin''' (FMU_CH6) switches between active stabilisation (FBWA) and neutral foils (MANUAL). It is wired active-low and fail-safe: a disconnected or open enable line disables foiling.
 
On boot the script enforces the parameters it needs (see the [[#Ardupilot settings|settings table]]) and falls to neutral foils on loss of the enable signal, stale sensor data, or a script error. It also publishes attitude, both height estimates, and a status word on the CAN bus for the datalogger (see [[#CAN Bus Format|CAN Bus Format]]).
 
Two height estimates run simultaneously and are both logged: the Lua roll-corrected value (currently used for control) and ArduPilot's EKF/rangefinder height. The first on-water runs will be flown with the foils disabled to collect this data and decide whether the EKF estimate is reliable enough to drive control.
 
The script is checked with luacheck and has been validated in ArduPilot SITL (software-in-the-loop) with the CAN bus simulated over UDP multicast.
 
== Ardupilot settings ==
To use the ardupilot as the foil control unit, some settings need to be changed. '''Most of the settings below are applied automatically at boot by the Lua script's parameter-enforcement routine''' — only <code>SCR_ENABLE</code> and the physical sensor mounting offsets (<code>RNGFNDx_POS_*</code>) must be set/measured manually. There are more ports available on the ardupilot; whenever more are used or changed the table will be updated.
{| class="wikitable sortable"
|+ Configuration of ardupilot
!Setting
!Value
!Description
!Reason
|-
|SCR_ENABLE
|1
|Enable Lua scripting
|Required to run the control script; must be set manually before the script can run.
|-
|INS_GYR_CAL
|0
|Controls the automatic gyro calibration.
|Gyro calibration requires that the unit be held as still as possible.
|-
|INITIAL_MODE
|5
|FBWA
|Fly By Wire A, the attitude-stabilisation mode the inner loop uses. More [https://ardupilot.org/plane/docs/fbwa-mode.html here].
|-
|SERVO1_FUNCTION
|77
|ElevonLeft
|Controls the left front foil assembly (wired to IO-CH1).
|-
|SERVO2_FUNCTION
|78
|ElevonRight
|Controls the right front foil assembly (wired to IO-CH2).
|-
|SERVO3_FUNCTION
|19
|Elevator
|Rear foil pitch command; the script reads this output and forwards it to the rear foil over CAN.
|-
|SERVO14_FUNCTION
|-1
|GPIO
|Frees FMU_CH6 so it can be read as the foil enable input.
|-
|BTN_ENABLE
|1
|Enable button (digital pin) function
|Enables reading the foil enable/disable input.
|-
|BTN_PIN1
|55
|GPIO pin 55 (FMU_CH6)
|Maps the enable input to FMU_CH6; active-low and fail-safe.
|-
|BTN_REPORT_SEND
|2
|Report button state over MAVLink
|Surfaces the enable state to the GCS.
|-
|CAN_P1_DRIVER
|1
|Enable CAN port 1
|CAN carries the height sensors, the rear foil command and telemetry.
|-
|CAN_D1_PROTOCOL
|10
|Scripting
|Lets the Lua script send/receive raw CAN frames on bus 1.
|-
|RNGFND1_TYPE / RNGFND2_TYPE
|36
|Lua scripting rangefinder
|The two height sensors, fed by the script.
|-
|RNGFND1_ORIENT / RNGFND2_ORIENT
|25
|Pitch270 (downward)
|Required for ArduPilot to treat the sensor as a height source.
|-
|RNGFND1/2_MIN_CM / MAX_CM
|40 / 150
|Valid range (cm)
|Range gate for the ultrasonic sensors.
|-
|RNGFND1/2_POS_X / _POS_Y / _POS_Z
|3.8 / ∓0.23 / −0.175
|Sensor mounting offset from the IMU (m; X fwd, Y right, Z down)
|Lets the height correction compensate the roll/pitch lever arm. CAD-measured: 3.8 m forward, 0.23 m left/right, 0.175 m above the IMU. RNGFND1 = left (−Y), RNGFND2 = right (+Y).
|-
|THR_FAILSAFE
|0
|Disable throttle/RC failsafe
|No RC receiver is fitted, so RC failsafe must not trigger.
|-
|ARSPD_USE
|0
|Do not use airspeed
|No airspeed sensor.
|-
|BRD_SAFETY_DEFLT
|0
|Safety switch disabled at boot
|No safety switch fitted; outputs must be live at boot (the enable pin is the safety interlock).
|-
|TERRAIN_ENABLE
|0
|Disable terrain following
|Not applicable; avoids interference with foil height control.
|-
|GPS_TYPE2
|5
|NMEA
|Sets the GPS data sent onto the serial data port.
|-
|SERIAL1_PROTOCOL
|2
|MAVLINK2
|Protocol on the Mission Planner serial port.
|-
|SERIAL1_BAUD
|57
|57600
|Baudrate of the Mission Planner serial port.
|-
|SERIAL4_PROTOCOL
|5
|GPS
|Protocol on the GPS serial port.
|-
|SERIAL4_BAUD
|9
|9600
|Baudrate of the GPS serial port.
|}
 
== CAN Bus Format ==
All traffic is classic CAN, standard 11-bit IDs, 1&nbsp;Mbit/s, little-endian unless noted. Inputs are produced by other nodes; outputs are produced by the Lua control script.
{| class="wikitable"
|+ CAN bus messages
!ID
!Direction
!Length
!Contents
|-
|0x011
|in
|3
|Front-left height sensor: [0] state (0x02 = Operational), [1..2] height in mm (uint16 LE)
|-
|0x012
|in
|3
|Front-right height sensor (same layout as 0x011)
|-
|0x010
|out
|2
|Rear foil servo command: PWM as uint16, '''big-endian''' (1500 = neutral)
|-
|0x250
|out
|6
|Telemetry – attitude: [0..1] roll, [2..3] pitch (int16, centidegrees), [4..5] yaw (uint16, centidegrees, 0..36000)
|-
|0x251
|out
|8
|Telemetry – state: [0..1] Lua roll-corrected height, [2..3] EKF height (uint16 mm, 0xFFFF = invalid), [4..5] status bits, [6] vehicle mode, [7] downward-rangefinder status
|}
The 0x251 status bits are: 0 wings enabled, 1 left sensor fresh, 2 right sensor fresh, 3 both fresh, 4 control height valid, 5 control source = EKF, 6 EKF healthy, 7 EKF initialised, 8 home set, 9 EKF origin set, 10 EKF height (HAGL) available, 11 EKF velocity available.
 
Byte 6 of <code>0x251</code> is the ArduPlane flight-mode number as reported by the autopilot. In normal operation the script only commands two: <code>0</code> = MANUAL (foils disabled / neutral) and <code>5</code> = FBWA (active stabilisation). Any other value means the mode was changed elsewhere (e.g. from the GCS); see the [https://ardupilot.org/plane/docs/flight-modes.html ArduPlane flight-mode list] for the full enumeration.
 
The steering angle come from the rudder controller and is planned to be used as roll input to the controller.
 
== Future plans ==
As of March 2026 the Lua control script provides ride-height control as an outer loop on top of FBWA, which already gives automatic altitude holding for the front foils; the rear foil is commanded over CAN. The earlier idea of switching to FBWB for altitude holding is therefore no longer required, though it remains an option for comparison.
 
Control-loop coefficients are still placeholders — tuning requires the boat in the water. The first runs will be passive (foils disabled) to collect attitude, height-sensor and EKF data over CAN and decide whether ArduPilot's EKF height estimate is reliable enough to use as the control input instead of the Lua-computed value.
 
Remaining integration work: feed the rudder/steering-angle CAN message into the controller and finalise the no-RC failsafe behaviour.
 
Some additional reading: https://ardupilot.org/plane/docs/common-sensor-testing.html
 
== Relevant links for configuring Ardupilot ==
https://ardupilot.org/copter/docs/common-gcs-only-operation.html
https://ardupilot.org/copter/docs/common-gcs-only-operation.html


Line 22: Line 237:
https://ardupilot.org/copter/docs/crash_check.html
https://ardupilot.org/copter/docs/crash_check.html


https://ardupilot.org/copter/docs/flight-modes.html --Stabalize mode seems best fit
https://ardupilot.org/copter/docs/flight-modes.html
 
https://ardupilot.org/plane/docs/fbwb-mode.html
 
https://ardupilot.org/plane/docs/fixed-wing-faq.html --Disable Gyro calibration on start-up
 
https://ardupilot.org/rover/docs/sonar-sensors.html --Two sonar sensors


https://ardupilot.org/copter/docs/stabilize-mode.html
https://ardupilot.org/dev/docs/plane-architecture.html --Plane architecture and files

Latest revision as of 10:37, 16 June 2026

Platform

Ease of development dictated the choice to run the control loop on existing hard- and software, which was chosen to be Ardupilot running on a orange cube.

Ardupilot PCB with the orange cube mounted.

To make use for our application a PCB has been designed to integrate into the hydrofoil design.

To connect to the ardupilot on the cube for tweaking settings and tuning control loops, Mission Planner is used. The control logic itself runs as a Lua script on the cube (see Lua control script). The following sections describe the tweaked settings and the on-board script.

Hardware

The cube is a plug-and-play unit and therefore does not need setup changes in the underlying ardupilot software. Only necessary settings should be tweaked.

Apart from the settings, tuning needs to be done in Mission Planner; this can only be done with the solar boat in the water and therefore no values are known for now.

The ardupilot PCB supports three servo motors, two front and one back motor. It has two isolated power supplies for the servo motors. Support for CAN and the cube is powered by the 24V input from the CAN connection.

It has its own GPS antenna and four UART serial ports, where Serial1 is used for the MAVLINK connection to Mission Planner running on a laptop. The two ultrasonic height sensors connect over the CAN bus (through an RS485-to-CAN interface PCB), not the cube's UART ports; the Lua control script reads them to keep the boat at its target ride height so it can 'surf' over waves.

For steering on foils an extra MCU is added onto the board, namely the ATSAMD20E18A. This MCU receives the steering position from the rudder and forwards it (it is intended to be put on the CAN bus for the control system to use).

Height Sensors

Currently testing ultrasonic height sensors, the RS485 version of the DYP-A02YY4W-V2.0, with a CAN-interface PCB in between that places the readings on the CAN bus.

Each sensor broadcasts a 3-byte frame at 8 Hz: byte 0 is a status enum (0x02 = Operational, anything else = no valid reading), bytes 1–2 are the measured height in millimetres (uint16, little-endian). The front-left sensor uses CAN ID 0x011 and the front-right 0x012 (see CAN Bus Format).

The sensors are mounted as far forward and outboard as possible to stay clear of the bow wake (CAD: 3.8 m forward, 0.23 m left/right, 0.175 m above the IMU). The trade-off is that their reading changes strongly with roll; the Lua script presents each sensor to ArduPilot as a downward scripting rangefinder (so ArduPilot median-filters and logs them) and applies a roll/pitch + lever-arm correction before using the values for control (see Lua control script).

Lua control script

The foil control logic runs as a Lua script on the cube (in the project git). It is a cascade that leans on ArduPilot's tested C++ attitude loop rather than re-implementing control in Lua:

  • Inner loop — ArduPlane FBWA (mode 5): stabilises pitch and roll attitude from the IMU and drives the three foils as control surfaces. The two front foils are configured as elevons and the rear foil as an elevator output.
  • Outer loop — the Lua script: reads the two CAN height sensors, computes a roll/pitch + lever-arm-corrected ride height, and turns the height error into a gentle pitch-target bias on the pitch input channel while holding roll level. Vertical-velocity damping uses the EKF's IMU-fused velocity estimate.

The rear foil is driven over CAN: the script reads ArduPilot's elevator output and sends it as a servo command (ID 0x010).

No RC transmitter is fitted — throttle and rudder are handled separately. Attitude targets are supplied via RC channel overrides from the script, refreshed every loop. A hardware enable pin (FMU_CH6) switches between active stabilisation (FBWA) and neutral foils (MANUAL). It is wired active-low and fail-safe: a disconnected or open enable line disables foiling.

On boot the script enforces the parameters it needs (see the settings table) and falls to neutral foils on loss of the enable signal, stale sensor data, or a script error. It also publishes attitude, both height estimates, and a status word on the CAN bus for the datalogger (see CAN Bus Format).

Two height estimates run simultaneously and are both logged: the Lua roll-corrected value (currently used for control) and ArduPilot's EKF/rangefinder height. The first on-water runs will be flown with the foils disabled to collect this data and decide whether the EKF estimate is reliable enough to drive control.

The script is checked with luacheck and has been validated in ArduPilot SITL (software-in-the-loop) with the CAN bus simulated over UDP multicast.

Ardupilot settings

To use the ardupilot as the foil control unit, some settings need to be changed. Most of the settings below are applied automatically at boot by the Lua script's parameter-enforcement routine — only SCR_ENABLE and the physical sensor mounting offsets (RNGFNDx_POS_*) must be set/measured manually. There are more ports available on the ardupilot; whenever more are used or changed the table will be updated.

Configuration of ardupilot
Setting Value Description Reason
SCR_ENABLE 1 Enable Lua scripting Required to run the control script; must be set manually before the script can run.
INS_GYR_CAL 0 Controls the automatic gyro calibration. Gyro calibration requires that the unit be held as still as possible.
INITIAL_MODE 5 FBWA Fly By Wire A, the attitude-stabilisation mode the inner loop uses. More here.
SERVO1_FUNCTION 77 ElevonLeft Controls the left front foil assembly (wired to IO-CH1).
SERVO2_FUNCTION 78 ElevonRight Controls the right front foil assembly (wired to IO-CH2).
SERVO3_FUNCTION 19 Elevator Rear foil pitch command; the script reads this output and forwards it to the rear foil over CAN.
SERVO14_FUNCTION
GPIO Frees FMU_CH6 so it can be read as the foil enable input.
BTN_ENABLE 1 Enable button (digital pin) function Enables reading the foil enable/disable input.
BTN_PIN1 55 GPIO pin 55 (FMU_CH6) Maps the enable input to FMU_CH6; active-low and fail-safe.
BTN_REPORT_SEND 2 Report button state over MAVLink Surfaces the enable state to the GCS.
CAN_P1_DRIVER 1 Enable CAN port 1 CAN carries the height sensors, the rear foil command and telemetry.
CAN_D1_PROTOCOL 10 Scripting Lets the Lua script send/receive raw CAN frames on bus 1.
RNGFND1_TYPE / RNGFND2_TYPE 36 Lua scripting rangefinder The two height sensors, fed by the script.
RNGFND1_ORIENT / RNGFND2_ORIENT 25 Pitch270 (downward) Required for ArduPilot to treat the sensor as a height source.
RNGFND1/2_MIN_CM / MAX_CM 40 / 150 Valid range (cm) Range gate for the ultrasonic sensors.
RNGFND1/2_POS_X / _POS_Y / _POS_Z 3.8 / ∓0.23 / −0.175 Sensor mounting offset from the IMU (m; X fwd, Y right, Z down) Lets the height correction compensate the roll/pitch lever arm. CAD-measured: 3.8 m forward, 0.23 m left/right, 0.175 m above the IMU. RNGFND1 = left (−Y), RNGFND2 = right (+Y).
THR_FAILSAFE 0 Disable throttle/RC failsafe No RC receiver is fitted, so RC failsafe must not trigger.
ARSPD_USE 0 Do not use airspeed No airspeed sensor.
BRD_SAFETY_DEFLT 0 Safety switch disabled at boot No safety switch fitted; outputs must be live at boot (the enable pin is the safety interlock).
TERRAIN_ENABLE 0 Disable terrain following Not applicable; avoids interference with foil height control.
GPS_TYPE2 5 NMEA Sets the GPS data sent onto the serial data port.
SERIAL1_PROTOCOL 2 MAVLINK2 Protocol on the Mission Planner serial port.
SERIAL1_BAUD 57 57600 Baudrate of the Mission Planner serial port.
SERIAL4_PROTOCOL 5 GPS Protocol on the GPS serial port.
SERIAL4_BAUD 9 9600 Baudrate of the GPS serial port.

CAN Bus Format

All traffic is classic CAN, standard 11-bit IDs, 1 Mbit/s, little-endian unless noted. Inputs are produced by other nodes; outputs are produced by the Lua control script.

CAN bus messages
ID Direction Length Contents
0x011 in 3 Front-left height sensor: [0] state (0x02 = Operational), [1..2] height in mm (uint16 LE)
0x012 in 3 Front-right height sensor (same layout as 0x011)
0x010 out 2 Rear foil servo command: PWM as uint16, big-endian (1500 = neutral)
0x250 out 6 Telemetry – attitude: [0..1] roll, [2..3] pitch (int16, centidegrees), [4..5] yaw (uint16, centidegrees, 0..36000)
0x251 out 8 Telemetry – state: [0..1] Lua roll-corrected height, [2..3] EKF height (uint16 mm, 0xFFFF = invalid), [4..5] status bits, [6] vehicle mode, [7] downward-rangefinder status

The 0x251 status bits are: 0 wings enabled, 1 left sensor fresh, 2 right sensor fresh, 3 both fresh, 4 control height valid, 5 control source = EKF, 6 EKF healthy, 7 EKF initialised, 8 home set, 9 EKF origin set, 10 EKF height (HAGL) available, 11 EKF velocity available.

Byte 6 of 0x251 is the ArduPlane flight-mode number as reported by the autopilot. In normal operation the script only commands two: 0 = MANUAL (foils disabled / neutral) and 5 = FBWA (active stabilisation). Any other value means the mode was changed elsewhere (e.g. from the GCS); see the ArduPlane flight-mode list for the full enumeration.

The steering angle come from the rudder controller and is planned to be used as roll input to the controller.

Future plans

As of March 2026 the Lua control script provides ride-height control as an outer loop on top of FBWA, which already gives automatic altitude holding for the front foils; the rear foil is commanded over CAN. The earlier idea of switching to FBWB for altitude holding is therefore no longer required, though it remains an option for comparison.

Control-loop coefficients are still placeholders — tuning requires the boat in the water. The first runs will be passive (foils disabled) to collect attitude, height-sensor and EKF data over CAN and decide whether ArduPilot's EKF height estimate is reliable enough to use as the control input instead of the Lua-computed value.

Remaining integration work: feed the rudder/steering-angle CAN message into the controller and finalise the no-RC failsafe behaviour.

Some additional reading: https://ardupilot.org/plane/docs/common-sensor-testing.html

Relevant links for configuring Ardupilot

https://ardupilot.org/copter/docs/common-gcs-only-operation.html

https://ardupilot.org/copter/docs/common-rangefinder-landingpage.html

https://ardupilot.org/copter/docs/setting-up-for-tuning.html

https://ardupilot.org/copter/docs/terrain-following-manual-modes.html

https://ardupilot.org/copter/docs/common-sensor-offset-compensation.html

https://ardupilot.org/copter/docs/crash_check.html

https://ardupilot.org/copter/docs/flight-modes.html

https://ardupilot.org/plane/docs/fbwb-mode.html

https://ardupilot.org/plane/docs/fixed-wing-faq.html --Disable Gyro calibration on start-up

https://ardupilot.org/rover/docs/sonar-sensors.html --Two sonar sensors

https://ardupilot.org/dev/docs/plane-architecture.html --Plane architecture and files